├── stream ├── minimap.gfx ├── minimap.ytd ├── circlemap.ytd └── squaremap.ytd ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.yml │ └── bug_report.yml ├── pull_request_template.md ├── auto_assign.yml ├── workflows │ ├── lint.yml │ └── stale.yml └── contributing.md ├── fxmanifest.lua ├── locales ├── ja.lua ├── en.lua ├── ar.lua ├── da.lua ├── sv.lua ├── et.lua ├── fi.lua ├── fr.lua ├── tr.lua ├── it.lua ├── sk.lua ├── de.lua ├── ge.lua ├── nl.lua ├── pt.lua ├── cs.lua ├── es.lua ├── pl.lua └── fa.lua ├── server.lua ├── README.md ├── html ├── brand-logo.svg ├── styles.css ├── responsive.css ├── index.html └── app.js ├── config.lua └── client.lua /stream/minimap.gfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbcore-framework/qb-hud/HEAD/stream/minimap.gfx -------------------------------------------------------------------------------- /stream/minimap.ytd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbcore-framework/qb-hud/HEAD/stream/minimap.ytd -------------------------------------------------------------------------------- /stream/circlemap.ytd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbcore-framework/qb-hud/HEAD/stream/circlemap.ytd -------------------------------------------------------------------------------- /stream/squaremap.ytd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbcore-framework/qb-hud/HEAD/stream/squaremap.ytd -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: QBCore Discord Server 4 | url: https://discord.gg/qbcore 5 | about: Ask questions, receive support, and discuss with the community in our Discord server. 6 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | ## Checklist 6 | 7 | 8 | 9 | - [ ] I have personally loaded this code into an updated qbcore project and checked all of its functionality. 10 | - [ ] My code fits the style guidelines. 11 | - [ ] My PR fits the contribution guidelines. 12 | -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | # Set to true to add reviewers to pull requests 2 | addReviewers: true 3 | 4 | # Set to true to add assignees to pull requests 5 | addAssignees: author 6 | 7 | # A list of reviewers to be added to pull requests (GitHub user name) 8 | reviewers: 9 | - /maintenance 10 | 11 | # A list of keywords to be skipped the process that add reviewers if pull requests include it 12 | skipKeywords: 13 | - wip 14 | 15 | # A number of reviewers added to the pull request 16 | # Set 0 to add all the reviewers (default: 0) 17 | numberOfReviewers: 0 -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | lua54 'yes' 4 | author 'Kakarot' 5 | description 'Heads-up display letting players track their hunger, thirst, stress, and more' 6 | version '2.2.0' 7 | 8 | shared_scripts { 9 | '@qb-core/shared/locale.lua', 10 | 'locales/en.lua', 11 | 'locales/*.lua', 12 | 'config.lua' 13 | } 14 | 15 | client_script 'client.lua' 16 | server_script 'server.lua' 17 | 18 | ui_page 'html/index.html' 19 | 20 | files { 21 | 'html/*', 22 | 'html/index.html', 23 | 'html/styles.css', 24 | 'html/responsive.css', 25 | 'html/app.js', 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: [push, pull_request_target] 3 | jobs: 4 | lint: 5 | name: Lint Resource 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | with: 10 | ref: ${{ github.event.pull_request.head.sha }} 11 | - name: Lint 12 | uses: iLLeniumStudios/fivem-lua-lint-action@v2 13 | with: 14 | capture: "junit.xml" 15 | args: "-t --formatter JUnit" 16 | extra_libs: mysql+polyzone+qblocales 17 | - name: Generate Lint Report 18 | if: always() 19 | uses: mikepenz/action-junit-report@v3 20 | with: 21 | report_paths: "**/junit.xml" 22 | check_name: Linting Report 23 | fail_on_failure: false -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. 2 | # 3 | # You can adjust the behavior by modifying this file. 4 | # For more information, see: 5 | # https://github.com/actions/stale 6 | name: Mark stale issues and pull requests 7 | 8 | on: 9 | schedule: 10 | - cron: '41 15 * * *' 11 | 12 | jobs: 13 | stale: 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | issues: write 18 | pull-requests: write 19 | 20 | steps: 21 | - uses: actions/stale@v5 22 | with: 23 | repo-token: ${{ secrets.GITHUB_TOKEN }} 24 | stale-issue-message: 'This issue has had 60 days of inactivity & will close within 7 days' 25 | stale-pr-message: 'This PR has had 60 days of inactivity & will close within 7 days' 26 | close-issue-label: 'Stale Closed' 27 | close-pr-label: 'Stale Closed' 28 | exempt-issue-labels: 'Suggestion' 29 | exempt-pr-labels: 'Suggestion' 30 | -------------------------------------------------------------------------------- /locales/ja.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD設定を読み込みました", 4 | ["hud_restart"] = "HUDを再起動しています", 5 | ["hud_start"] = "HUDを起動しました", 6 | ["hud_command_info"] = "このコマンドは現在のHUD設定をリセットします", 7 | ["load_square_map"] = "スクエアマップ読み込み中...", 8 | ["loaded_square_map"] = "スクエアマップ読み込み完了", 9 | ["load_circle_map"] = "サークルマップ読み込み中...", 10 | ["loaded_circle_map"] = "サークルマップ読み込み完了", 11 | ["cinematic_on"] = "シネマティックモードを有効にしました", 12 | ["cinematic_off"] = "シネマティックモードを無効にしました", 13 | ["engine_on"] = "エンジン始動", 14 | ["engine_off"] = "エンジン停止", 15 | ["low_fuel"] = "燃料が残りわずかです!", 16 | ["access_denied"] = "権限がありません!", 17 | ["stress_gain"] = "ストレスを感じた!", 18 | ["stress_removed"] = "リラックスした気分" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'ja' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/en.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD Settings Loaded!", 4 | ["hud_restart"] = "HUD Is Restarting!", 5 | ["hud_start"] = "HUD Is Now Started!", 6 | ["hud_command_info"] = "This command resets your current HUD settings!", 7 | ["load_square_map"] = "Square Map Loading...", 8 | ["loaded_square_map"] = "Square Map Has Loaded!", 9 | ["load_circle_map"] = "Circle Map Loading...", 10 | ["loaded_circle_map"] = "Circle Map Has Loaded!", 11 | ["cinematic_on"] = "Cinematic Mode On!", 12 | ["cinematic_off"] = "Cinematic Mode Off!", 13 | ["engine_on"] = "Engine Started!", 14 | ["engine_off"] = "Engine Shut Down!", 15 | ["low_fuel"] = "Fuel Level Low!", 16 | ["access_denied"] = "You Are Not Authorized!", 17 | ["stress_gain"] = "Feeling More Stressed!", 18 | ["stress_removed"] = "Feeling More Relaxed!" 19 | } 20 | } 21 | 22 | Lang = Lang or Locale:new({ 23 | phrases = Translations, 24 | warnOnMissing = true 25 | }) 26 | -------------------------------------------------------------------------------- /locales/ar.lua: -------------------------------------------------------------------------------- 1 | 2 | local Translations = { 3 | notify = { 4 | ["hud_settings_loaded"] = "تم تحميل إعدادات الهود", 5 | ["hud_restart"] = "تم اعادة الهود للوضع الاصلي", 6 | ["hud_start"] = "تم تشغيل الهود", 7 | ["hud_command_info"] = "هذا الأمر يعيد ضبط إعدادات شاشة الهود الى الوضع الاصلي", 8 | ["load_square_map"] = "تحميل خريطة مربعة", 9 | ["loaded_square_map"] = "تم تحميل خريطة مربعة", 10 | ["load_circle_map"] = "تحميل خريطة الدائرة", 11 | ["loaded_circle_map"] = "تم تحميل خريطة الدائرة", 12 | ["cinematic_on"] = "الوضع السينمائي قيد التشغيل", 13 | ["cinematic_off"] = "الوضع السينمائي قيد الايقاف", 14 | ["engine_on"] = "بدأ المحرك", 15 | ["engine_off"] = "اغلاق المحرك", 16 | ["low_fuel"] = "مستوى الوقود منخفض", 17 | ["access_denied"] = "غير مسموح لك القيام بذالك", 18 | ["stress_gain"] = "الشعور بمزيد من التوتر", 19 | ["stress_removed"] = "الشعور براحة أكبر" 20 | } 21 | } 22 | 23 | if GetConvar('qb_locale', 'en') == 'ar' then 24 | Lang = Locale:new({ 25 | phrases = Translations, 26 | warnOnMissing = true, 27 | fallbackLang = Lang, 28 | }) 29 | end 30 | -------------------------------------------------------------------------------- /locales/da.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD indstillinger indlæst!", 4 | ["hud_restart"] = "HUD genstarter!", 5 | ["hud_start"] = "HUD er nu startet!", 6 | ["hud_command_info"] = "Denne command nulstiller alle HUD indstillinger!", 7 | ["load_square_map"] = "Firkantet map indlæses...", 8 | ["loaded_square_map"] = "Firkantet map indlæst!", 9 | ["load_circle_map"] = "Cirkel map indlæses...", 10 | ["loaded_circle_map"] = "Cikel map indlæst!", 11 | ["cinematic_on"] = "Cinematic mode er aktiveret!", 12 | ["cinematic_off"] = "Cinematic mode er deaktiveret!", 13 | ["engine_on"] = "Motor startet!", 14 | ["engine_off"] = "Motor slukket!", 15 | ["low_fuel"] = "Lav brændstofstand!", 16 | ["access_denied"] = "Du har ikke adgang!", 17 | ["stress_gain"] = "Du føler dig mere stresset!", 18 | ["stress_removed"] = "Du føles mere afslappet!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'da' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/sv.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD Inställningar laddade!", 4 | ["hud_restart"] = "HUD startar om!", 5 | ["hud_start"] = "HUD är startad!", 6 | ["hud_command_info"] = "Detta kommando nollställer dina nuvarande HUD-inställningar!", 7 | ["load_square_map"] = "Kvadratisk karta laddas!", 8 | ["loaded_square_map"] = "Kvadratisk karta har laddats!", 9 | ["load_circle_map"] = "Cirkelkartan laddas!", 10 | ["loaded_circle_map"] = "Cirkelkartan har laddats!", 11 | ["cinematic_on"] = "Bioläge på!", 12 | ["cinematic_off"] = "Bioläge av!", 13 | ["engine_on"] = "Motorn startade!", 14 | ["engine_off"] = "Motorn stängs av!", 15 | ["low_fuel"] = "Låg bränslenivå!", 16 | ["access_denied"] = "Du är inte behörighet att göra detta!", 17 | ["stress_gain"] = "Känner dig mer stressad!", 18 | ["stress_removed"] = "Känner dig mer avslappnad!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'sv' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/et.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD-i seaded on laaditud!", 4 | ["hud_restart"] = "HUD taaskäivitub!", 5 | ["hud_start"] = "HUD on nüüd käivitatud!", 6 | ["hud_command_info"] = "See käsk lähtestab teie praegused HUD-seaded!", 7 | ["load_square_map"] = "Ruutkaardi laadimine...", 8 | ["loaded_square_map"] = "Ruutkaart on laaditud!", 9 | ["load_circle_map"] = "Ringi kaardi laadimine...", 10 | ["loaded_circle_map"] = "Ringi kaart on laaditud!", 11 | ["cinematic_on"] = "Cinematic režiim sees!", 12 | ["cinematic_off"] = "Cinematic režiim väljas!", 13 | ["engine_on"] = "Mootor käivitatud!", 14 | ["engine_off"] = "Mootor seisatud!", 15 | ["low_fuel"] = "Kütusetase madal!", 16 | ["access_denied"] = "Te pole volitatud!", 17 | ["stress_gain"] = "Tunnen end rohkem stressis!", 18 | ["stress_removed"] = "Tunnen end rohkem lõdvestunult!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'et' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/fi.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "Hudin asetukset ladattu!", 4 | ["hud_restart"] = "Hudi resettaantuu!", 5 | ["hud_start"] = "Hudi päällä!", 6 | ["hud_command_info"] = "Tämä komento vaihtaa hudisi asetukset!", 7 | ["load_square_map"] = "Neliökartta latautuu...", 8 | ["loaded_square_map"] = "Neliökartta ladattu!", 9 | ["load_circle_map"] = "Mappi ladattu...", 10 | ["loaded_circle_map"] = "Pyöreä mappi ladattu!", 11 | ["cinematic_on"] = "Elokuvamode päällä!", 12 | ["cinematic_off"] = "Elokuvamode suljettu!", 13 | ["engine_on"] = "Moottori käynnistetty!", 14 | ["engine_off"] = "Moottori sammutettu!", 15 | ["low_fuel"] = "Bensasi on lopussa!", 16 | ["access_denied"] = "Eipä ollut tarpeaksi oikeuksia!", 17 | ["stress_gain"] = "Stressisi nousee!", 18 | ["stress_removed"] = "Stressisi on nyt loppunut! Otathan ihan clillisti sit" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'fi' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/fr.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "Paramètres du HUD chargés!", 4 | ["hud_restart"] = "L'HUD redémarre!", 5 | ["hud_start"] = "L'HUD a demarré!", 6 | ["hud_command_info"] = "Cette commande réinitialise vos paramètre d'HUD!", 7 | ["load_square_map"] = "Chargement de la carte carrée...", 8 | ["loaded_square_map"] = "La carte carrée à chargée!", 9 | ["load_circle_map"] = "Chargement de la carte ronde...", 10 | ["loaded_circle_map"] = "La carte ronde à chargée!", 11 | ["cinematic_on"] = "Mode cinématique activé!", 12 | ["cinematic_off"] = "Mode cinématique désactivé!", 13 | ["engine_on"] = "Moteur allumé!", 14 | ["engine_off"] = "Moteur éteint!", 15 | ["low_fuel"] = "Niveau d'essence bas!", 16 | ["access_denied"] = "Vous n'êtes pas autorisé!", 17 | ["stress_gain"] = "Vous stressez!", 18 | ["stress_removed"] = "Vous-vous relaxez!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'fr' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/tr.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD Ayarları Yüklendi!", 4 | ["hud_restart"] = "HUD Yeniden Başlatılıyor!", 5 | ["hud_start"] = "HUD Şimdi Başladı!", 6 | ["hud_command_info"] = "Bu komut, mevcut HUD ayarlarınızı sıfırlar!", 7 | ["load_square_map"] = "Kare Harita Yükleniyor...", 8 | ["loaded_square_map"] = "Kare Harita Yüklendi!", 9 | ["load_circle_map"] = "Çember Haritası Yükleniyor...", 10 | ["loaded_circle_map"] = "Daire Haritası Yüklendi!", 11 | ["cinematic_on"] = "Sinema Modu Açık!", 12 | ["cinematic_off"] = "Sinema Modu Kapalı!", 13 | ["engine_on"] = "Motor Çalıştırıldı!", 14 | ["engine_off"] = "Motor Kapatıldı!", 15 | ["low_fuel"] = "Yakıt Seviyesi Düşük!", 16 | ["access_denied"] = "You Are Not Authorized!", 17 | ["stress_gain"] = "Daha Stresli Hissediyorum!", 18 | ["stress_removed"] = "Daha Rahatlamış Hissediyorum!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'tr' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/it.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "Impostazioni HUD Caricate!", 4 | ["hud_restart"] = "L\'HUD si sta restartando!", 5 | ["hud_start"] = "L\'HUD si sta avviando!", 6 | ["hud_command_info"] = "Questo comando resetta le impostazioni dell\'HUD!", 7 | ["load_square_map"] = "Caricando Mappa Quadrata...", 8 | ["loaded_square_map"] = "Mappa Quadrata Caricata!", 9 | ["load_circle_map"] = "Caricando Mappa Rotonda...", 10 | ["loaded_circle_map"] = "Mappa Rotonda Caricata!", 11 | ["cinematic_on"] = "Modalità Cinematica On!", 12 | ["cinematic_off"] = "Modalità Cinematica Off!", 13 | ["engine_on"] = "Motore Avviato!", 14 | ["engine_off"] = "Motore Spento!", 15 | ["low_fuel"] = "Livello Carburante Basso!", 16 | ["access_denied"] = "Non Sei Autorizzato!", 17 | ["stress_gain"] = "Ti Stai Stressando!", 18 | ["stress_removed"] = "Ti Stai Rilassando!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'it' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/sk.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD nastavenia boli načítané!", 4 | ["hud_restart"] = "HUD sa reštartuje!", 5 | ["hud_start"] = "HUD je zapnutý!", 6 | ["hud_command_info"] = "Tento príkaz reštartuje tvoje aktuálne HUD nastavenia!", 7 | ["load_square_map"] = "Square Map sa načítava...", 8 | ["loaded_square_map"] = "Square Map sa načítala!", 9 | ["load_circle_map"] = "Circle Map sa načítava...", 10 | ["loaded_circle_map"] = "Circle Map sa načítala!", 11 | ["cinematic_on"] = "Filmový režim je zapnutý!", 12 | ["cinematic_off"] = "Filmový režim je vypnutý!", 13 | ["engine_on"] = "Motor je naštartovaný!", 14 | ["engine_off"] = "Motor je vypnutý!", 15 | ["low_fuel"] = "Nízka hladina paliva!", 16 | ["access_denied"] = "Nemáš oprávnenie!", 17 | ["stress_gain"] = "Pocituješ väčší stres!", 18 | ["stress_removed"] = "Pocituješ uvoľnenie!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'sk' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/de.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD Einstellungen geladen!", 4 | ["hud_restart"] = "HUD wird neugestartet!", 5 | ["hud_start"] = "HUD ist nun gestartet!", 6 | ["hud_command_info"] = "Dieser Befehl setzt deine jetzigen Einstellungen zurück!", 7 | ["load_square_map"] = "Quadratische Karte lädt..", 8 | ["loaded_square_map"] = "Quadratische Karte wurde geladen!", 9 | ["load_circle_map"] = "Kreiskarte lädt...", 10 | ["loaded_circle_map"] = "Kreiskarte wurde geladen!", 11 | ["cinematic_on"] = "Kino Modus aktiviert!", 12 | ["cinematic_off"] = "Kino Modus deaktiviert!", 13 | ["engine_on"] = "Motor ist nun an!", 14 | ["engine_off"] = "Motor ist nun aus!", 15 | ["low_fuel"] = "Tank Status niedrig!", 16 | ["access_denied"] = "Du bist nicht autorisiert!", 17 | ["stress_gain"] = "Stesslevel steigt!", 18 | ["stress_removed"] = "Du entspannst gerade!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'de' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/ge.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD პარამეტრების ჩატვირთვა!", 4 | ["hud_restart"] = "HUD -ი რესტარტდება!", 5 | ["hud_start"] = "HUD -ი ჩართულია!", 6 | ["hud_command_info"] = "ეს ბრძანება დაარესეტებს ასებულ მონაცმებს!", 7 | ["load_square_map"] = "რუკა იტვირთება...", 8 | ["loaded_square_map"] = "რუკა ჩაიტვირთა!", 9 | ["load_circle_map"] = "რგვალი რუკა იტვირთება...", 10 | ["loaded_circle_map"] = "მრგვალი რუკა ჩაიტვირთა!", 11 | ["cinematic_on"] = "Cinematic რეჯიმის ჩართვა!", 12 | ["cinematic_off"] = "Cinematic რეჟიმის გათიშვა!", 13 | ["engine_on"] = "ავტომობილის დაქოქვა!", 14 | ["engine_off"] = "ავტომობილის ჩაქრობა!", 15 | ["low_fuel"] = "საწვავის ავზის მაჩვენებელი მინიმუმზე!", 16 | ["access_denied"] = "არ ხარ ავტორიზირებული!", 17 | ["stress_gain"] = "თავს გრძნობ მეტი სტრესის ქვეშ!", 18 | ["stress_removed"] = "თავს გრძნობ რელაქსირებულად!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'ge' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/nl.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "HUD instellingen geladen!", 4 | ["hud_restart"] = "HUD is aan het herstarten!", 5 | ["hud_start"] = "HUD is herstart!", 6 | ["hud_command_info"] = "Deze command reset jouw huidige HUD instellingen!", 7 | ["load_square_map"] = "Vierkante map is aan het laden...", 8 | ["loaded_square_map"] = "Vierkante map is geladen!", 9 | ["load_circle_map"] = "Cirkel map is aan het laden...", 10 | ["loaded_circle_map"] = "Cirkel map is geladen!", 11 | ["cinematic_on"] = "Bioscoop modus aan!", 12 | ["cinematic_off"] = "Bioscoop modus uit!", 13 | ["engine_on"] = "Motor aangezet!", 14 | ["engine_off"] = "Motor uitgezet!", 15 | ["low_fuel"] = "Laag brandstofniveau!", 16 | ["access_denied"] = "Je bent niet gemachtigd!", 17 | ["stress_gain"] = "Je voelt je meer gestrest!", 18 | ["stress_removed"] = "Je voelt je meer relaxed!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'nl' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/pt.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "Definições Do HUD Carregadas!", 4 | ["hud_restart"] = "O HUD Está A Reiniciar!", 5 | ["hud_start"] = "O HUD Está Agora Iniciada!", 6 | ["hud_command_info"] = "Este comando reseta as definições do teu HUD!", 7 | ["load_square_map"] = "A Carregar Mapa Quadrado...", 8 | ["loaded_square_map"] = "Mapa Quadrado Carregado!", 9 | ["load_circle_map"] = "A Carregar Mapa Redondo...", 10 | ["loaded_circle_map"] = "Mapa Redondo Carregado!", 11 | ["cinematic_on"] = "Modo Cinematic Ativado!", 12 | ["cinematic_off"] = "Modo Cinematic Desativado!", 13 | ["engine_on"] = "Motor Ligado!", 14 | ["engine_off"] = "Motor Desligado!", 15 | ["low_fuel"] = "Nível Do Combustivel Em Baixo!", 16 | ["access_denied"] = "Não Estás Autorizado!", 17 | ["stress_gain"] = "A Sentir-me Mais Stressado(a)!", 18 | ["stress_removed"] = "A Sentir-me Mais Calmo(a)!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'pt' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/cs.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "Nastavení HUD načteno!", 4 | ["hud_restart"] = "HUD se restartuje!", 5 | ["hud_start"] = "HUD je nyní zapnutý!", 6 | ["hud_command_info"] = "Tento příkaz resetuje vaše momentální nastavení HUD!", 7 | ["load_square_map"] = "Načítání čtvercové mapy...", 8 | ["loaded_square_map"] = "Čtvercová mapa byla načtena!", 9 | ["load_circle_map"] = "Kruhová mapa se načítá...", 10 | ["loaded_circle_map"] = "Kruhová mapa byla načtena!", 11 | ["cinematic_on"] = "Cinematic Mode On!", -- Same as in English 12 | ["cinematic_off"] = "Cinematic Mode Off!", -- Same as in English 13 | ["engine_on"] = "Motor nastartován!", 14 | ["engine_off"] = "Motor vypnut!", 15 | ["low_fuel"] = "Nedostatek paliva!", 16 | ["access_denied"] = "Na toto nemáš oprávnění!", 17 | ["stress_gain"] = "Cítíš se být vystresovaná!", 18 | ["stress_removed"] = "Cítíš se volněj!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'cs' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/es.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "Configuración de HUD cargada.", 4 | ["hud_restart"] = "HUD reiniciando.", 5 | ["hud_start"] = "HUD iniciado.", 6 | ["hud_command_info"] = "Este comando restablece la configuración del HUD", 7 | ["load_square_map"] = "Cargando mapa cuadrado.", 8 | ["loaded_square_map"] = "Cargado mapa cuadrado.", 9 | ["load_circle_map"] = "Cargando mapa circular.", 10 | ["loaded_circle_map"] = "Cargado mapa circular.", 11 | ["cinematic_on"] = "Modo cinematográfico activado", 12 | ["cinematic_off"] = "Modo cinematográfico desactivado.", 13 | ["engine_on"] = "Motor encendido", 14 | ["engine_off"] = "Motor apagado", 15 | ["low_fuel"] = "Nivel de gasolina bajo", 16 | ["access_denied"] = "No estas autorizado para hacer eso", 17 | ["stress_gain"] = "Te estás sintiendo más estresado/a.", 18 | ["stress_removed"] = "Te estás sintiendo más relajado/a." 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'es' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/pl.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "Załadowano ustawienia HUD!", 4 | ["hud_restart"] = "HUD uruchamia się ponownie!", 5 | ["hud_start"] = "HUD jest już uruchomiony!", 6 | ["hud_command_info"] = "To polecenie resetuje twoje obecne ustawienia HUD!", 7 | ["load_square_map"] = "Ładowanie kwadratowej mapy...", 8 | ["loaded_square_map"] = "Załadowano kwadratową mapę!", 9 | ["load_circle_map"] = "Ładowanie okrągłej mapy...", 10 | ["loaded_circle_map"] = "Załadowano okrągłą mapę!", 11 | ["cinematic_on"] = "Tryb kinowy włączony!", 12 | ["cinematic_off"] = "Tryb kinowy wyłączony!", 13 | ["engine_on"] = "Silnik uruchomiony!", 14 | ["engine_off"] = "Wyłączenie silnika!", 15 | ["low_fuel"] = "Niski poziom paliwa!", 16 | ["access_denied"] = "Nie jesteś upoważniony!", 17 | ["stress_gain"] = "Czuję się bardziej zestresowany!", 18 | ["stress_removed"] = "Czuję się bardziej zrelaksowany!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'pl' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /locales/fa.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notify = { 3 | ["hud_settings_loaded"] = "Tanzimat HUD Bargozari Shod!", 4 | ["hud_restart"] = "Dar Hale Bargozari Mojadad HUD!", 5 | ["hud_start"] = "HUD Bargozari Shod!", 6 | ["hud_command_info"] = "In Dastor Tanzimat HUD Feli Shoma Ra Taghir Midahad!", 7 | ["load_square_map"] = "Nagsheye Mostatili Bargozari Shod...", 8 | ["loaded_square_map"] = "Nagsheye Mostatili Bargozari Shod!", 9 | ["load_circle_map"] = "Nagsheye Daayerei Bargozari Shod...", 10 | ["loaded_circle_map"] = "Nagsheye Daayerei Bargozari Shod!", 11 | ["cinematic_on"] = "Halat Sinemayi Faal Shod!", 12 | ["cinematic_off"] = "Halat Sinemayi Gheyre Faal Shod!", 13 | ["engine_on"] = "Motor Roshan Shod!", 14 | ["engine_off"] = "Motor Khamosh Shod!", 15 | ["low_fuel"] = "Sokht Dar Hale Etmam Ast!", 16 | ["access_denied"] = "Shoma Mojaz Be In Kar Nistid!", 17 | ["stress_gain"] = "Mizan Estres Dar Hale Afzayesh Ast!", 18 | ["stress_removed"] = "Mizan Estres Dar Hale Kahesh Ast!" 19 | } 20 | } 21 | 22 | if GetConvar('qb_locale', 'en') == 'fa' then 23 | Lang = Locale:new({ 24 | phrases = Translations, 25 | warnOnMissing = true, 26 | fallbackLang = Lang, 27 | }) 28 | end 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea for QBCore 3 | title: "[SUGGESTION]" 4 | labels: enhancement 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Please use our Discord Server to ask questions and receive support: https://discord.gg/qbcore 10 | - type: textarea 11 | id: problem 12 | attributes: 13 | label: The problem 14 | description: A clear and concise description of what the problem is, or what feature you want to be implemented. 15 | placeholder: | 16 | Some examples: 17 | I'm frustrated that ... 18 | It would be nice if ... 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: solution 23 | attributes: 24 | label: Ideal solution 25 | description: A clear and concise description of what you want to happen, with as much detail as possible. 26 | validations: 27 | required: true 28 | - type: textarea 29 | id: alternatives 30 | attributes: 31 | label: Alternative solutions 32 | description: A clear and concise description of any alternative solutions or features you've considered. 33 | - type: textarea 34 | id: additional 35 | attributes: 36 | label: Additional context 37 | description: If you have any other context about the problem such as screenshots or videos, add them here. 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Create a report to help us improve or fix something 3 | title: "[BUG]" 4 | labels: bug 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thank you for taking the time to fill out a bug report! 10 | Please use our Discord Server to ask questions and receive support: https://discord.gg/qbcore 11 | - type: input 12 | id: summary 13 | attributes: 14 | label: Summary 15 | description: Write a short and concise description of your bug. 16 | validations: 17 | required: true 18 | - type: textarea 19 | id: repro 20 | attributes: 21 | label: Reproduction 22 | description: What did you do to make this happen? 23 | placeholder: | 24 | 1. Using ... 25 | 2. Do ... 26 | 3. Then use ... 27 | 4. See error 28 | validations: 29 | required: true 30 | - type: textarea 31 | id: expected 32 | attributes: 33 | label: Expected behavior 34 | description: What did you expect to happen? 35 | validations: 36 | required: true 37 | - type: textarea 38 | id: actual 39 | attributes: 40 | label: Actual behavior 41 | description: What actually happened? 42 | validations: 43 | required: true 44 | - type: textarea 45 | id: additional 46 | attributes: 47 | label: Additional context 48 | description: If you have any other context about the problem such as screenshots or videos, add them here. 49 | - type: input 50 | id: updated 51 | attributes: 52 | label: Last Updated 53 | description: When have you last updated? 54 | placeholder: e.g. last week, today 55 | validations: 56 | required: true 57 | - type: input 58 | id: custom 59 | attributes: 60 | label: Custom Resources 61 | description: Are you using custom resources? Which ones? 62 | placeholder: e.g. zdiscord, qb-target 63 | validations: 64 | required: true 65 | - type: input 66 | id: renamed 67 | attributes: 68 | label: Resource Rename 69 | description: Have you renamed this resource from `qb-` to something custom? 70 | validations: 71 | required: true 72 | -------------------------------------------------------------------------------- /server.lua: -------------------------------------------------------------------------------- 1 | local QBCore = exports['qb-core']:GetCoreObject() 2 | local ResetStress = false 3 | 4 | QBCore.Commands.Add('cash', 'Check Cash Balance', {}, false, function(source, _) 5 | local Player = QBCore.Functions.GetPlayer(source) 6 | local cashamount = Player.PlayerData.money.cash 7 | TriggerClientEvent('hud:client:ShowAccounts', source, 'cash', cashamount) 8 | end) 9 | 10 | QBCore.Commands.Add('bank', 'Check Bank Balance', {}, false, function(source, _) 11 | local Player = QBCore.Functions.GetPlayer(source) 12 | local bankamount = Player.PlayerData.money.bank 13 | TriggerClientEvent('hud:client:ShowAccounts', source, 'bank', bankamount) 14 | end) 15 | 16 | QBCore.Commands.Add('dev', 'Enable/Disable developer Mode', {}, false, function(source, _) 17 | TriggerClientEvent('qb-admin:client:ToggleDevmode', source) 18 | end, 'admin') 19 | 20 | RegisterNetEvent('hud:server:GainStress', function(amount) 21 | if Config.DisableStress then return end 22 | local src = source 23 | local Player = QBCore.Functions.GetPlayer(src) 24 | local Job = Player.PlayerData.job.name 25 | local JobType = Player.PlayerData.job.type 26 | local newStress 27 | if not Player or Config.WhitelistedJobs[JobType] or Config.WhitelistedJobs[Job] then return end 28 | if not ResetStress then 29 | if not Player.PlayerData.metadata['stress'] then 30 | Player.PlayerData.metadata['stress'] = 0 31 | end 32 | newStress = Player.PlayerData.metadata['stress'] + amount 33 | if newStress <= 0 then newStress = 0 end 34 | else 35 | newStress = 0 36 | end 37 | if newStress > 100 then 38 | newStress = 100 39 | end 40 | Player.Functions.SetMetaData('stress', newStress) 41 | TriggerClientEvent('hud:client:UpdateStress', src, newStress) 42 | TriggerClientEvent('QBCore:Notify', src, Lang:t('notify.stress_gain'), 'error', 1500) 43 | end) 44 | 45 | RegisterNetEvent('hud:server:RelieveStress', function(amount) 46 | if Config.DisableStress then return end 47 | local src = source 48 | local Player = QBCore.Functions.GetPlayer(src) 49 | local newStress 50 | if not Player then return end 51 | if not ResetStress then 52 | if not Player.PlayerData.metadata['stress'] then 53 | Player.PlayerData.metadata['stress'] = 0 54 | end 55 | newStress = Player.PlayerData.metadata['stress'] - amount 56 | if newStress <= 0 then newStress = 0 end 57 | else 58 | newStress = 0 59 | end 60 | if newStress > 100 then 61 | newStress = 100 62 | end 63 | Player.Functions.SetMetaData('stress', newStress) 64 | TriggerClientEvent('hud:client:UpdateStress', src, newStress) 65 | TriggerClientEvent('QBCore:Notify', src, Lang:t('notify.stress_removed')) 66 | end) 67 | 68 | QBCore.Functions.CreateCallback('hud:server:getMenu', function(_, cb) 69 | cb(Config.Menu) 70 | end) 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Things you should know: 3 | * To open the menu in-game the **default key** is **"I"** or you can type **"/menu"** 4 | * Your settings will **always** be **stored locally**, so even if you delete the resource it **will** keep your current settings. The **only** way you can wipe the local storage sucessfully is by clicking the **"Reset Settings"** button on the in-game menu 5 | * If you want the new super snazzy sound effects for the menu, you'll need to download the latest update of [interact-sound](https://github.com/qbcore-framework/interact-sound)
6 | (comes with new open menu sound, close menu sound, click menu sound) 7 | * If you receive ```attempt to index a nil value (global 'Lang')``` in your F8 console, the fastest way you can fix that issue is by downloading a new version via txAdminRecipe but if you are unable to do that because of the progress you’ve made on your existing build; you’ll have to unfortunately go through and download each one from the GitHub which I do not recommend. Save yourself a lot of time and pain by just downloading the recipe! 8 | 9 | # FAQ 10 | ## 11 | **Q:** Why do my borders not align with the maps? 12 | 13 | **A:** Most of the time it generally means your safezone is not set to default in your GTA settings. (Settings/Display/"Restore Defaults") 14 | ## 15 | 16 | ## 17 | **Q:** How do I enable dev mode? 18 | 19 | **A:** Simple! All you have to do is type /admin and navigate through the menu to the last section called "Developer Options" and inside there you should see "Dev Mode", this will keep you invincible and add a cool developer icon in your circles/radials 20 | ## 21 | 22 | ## 23 | **Q:** What does the purple circle/radial do? 24 | 25 | **A:** That is your harness indicator! When you have the item "harness" in your inventory and while in a vehicle it will appear. Also, when you use your item "harness", the circle/radial will reflect the amount of uses left and decrease overtime. 26 | ## 27 | 28 | # Previews 29 | ### menu config (this is just a preview more options included than what is shown here) 30 | ![menu](https://user-images.githubusercontent.com/91661118/149598723-b34bb93d-8885-4b3a-a0cc-ab68d756a449.PNG) 31 | ### all radials 32 | ![all radials](https://user-images.githubusercontent.com/91661118/143668930-e9475c53-284c-4054-ad9c-88aa98f76768.png) 33 | ### dead health 34 | ![dead](https://user-images.githubusercontent.com/91661118/143668617-3f41913f-506e-4c40-bc97-99c0e02eaec6.png) 35 | ### engine health 36 | ![engine](https://user-images.githubusercontent.com/91661118/143668642-22269059-8220-4b78-8f24-3c3661b7e82f.png) 37 | ### altitude 38 | ![altitude](https://user-images.githubusercontent.com/91661118/143668687-89ae10b6-9acc-4d68-845d-97db67d3d6de.png) 39 | ### parachute 40 | ![parachute](https://user-images.githubusercontent.com/91661118/143668699-a9d50ee4-1168-401b-bf92-8ba80a696e6e.png) 41 | ### armed 42 | ![armed](https://user-images.githubusercontent.com/91661118/143668646-baac9848-56e5-436b-922a-b35e50ed335f.png) 43 | ### cinematic 44 | ![cinematic](https://user-images.githubusercontent.com/91661118/143668651-74e90ac0-11ad-447a-b27c-1542dd10edfd.png) 45 | ### cruise 46 | ![cruise](https://user-images.githubusercontent.com/91661118/143668654-1b843009-c791-4482-807d-352b75707d42.png) 47 | ### harness 48 | ![harness](https://user-images.githubusercontent.com/91661118/143668664-bd03289a-286f-4165-9447-25b16b5b0c8e.png) 49 | ### cash 50 | ![cash](https://user-images.githubusercontent.com/91661118/143668667-a8e2e856-94be-45c4-9751-39e71315b303.png) 51 | ### bank 52 | ![bank](https://user-images.githubusercontent.com/91661118/143668668-fed140e6-9043-4daa-8aba-36feac3f9b78.png) 53 | ### nitro 54 | ![nitro](https://user-images.githubusercontent.com/91661118/143668672-8a164eb0-aca5-4e00-a99f-56c64e4d5069.png) 55 | ### stamina 56 | ![stamina](https://user-images.githubusercontent.com/91661118/143668678-3327c0bf-7e3b-4fe5-b6e5-da6e4054a47a.png) 57 | ### oxygen 58 | ![oxygen](https://user-images.githubusercontent.com/91661118/143668693-d623822b-fc78-499a-baa3-a86e29504044.png) 59 | ### radio (outdated color) 60 | ![radio](https://user-images.githubusercontent.com/91661118/143668707-eb4bb5e7-5900-4dd8-b500-5fc745a7c146.png) 61 | -------------------------------------------------------------------------------- /html/brand-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 11 | 12 | 53 | 55 | 57 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = {} 2 | Config.OpenMenu = 'I' -- https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/ 3 | Config.StressChance = 0.1 -- Default: 10% -- Percentage Stress Chance When Shooting (0-1) 4 | Config.UseMPH = true -- If true speed math will be done as MPH, if false KPH will be used (YOU HAVE TO CHANGE CONTENT IN STYLES.CSS TO DISPLAY THE CORRECT TEXT) 5 | Config.MinimumStress = 50 -- Minimum Stress Level For Screen Shaking 6 | Config.MinimumSpeedUnbuckled = 50 -- Going Over This Speed Unbuckled Will Cause Stress 7 | Config.MinimumSpeed = 100 -- Going Over This Speed While Buckled Will Cause Stress 8 | Config.DisableStress = false -- If true will disable stress completely for all players 9 | 10 | -- Stress 11 | Config.WhitelistedWeaponArmed = { -- Disable showing armed icon from weapons in this table 12 | -- miscellaneous 13 | [`weapon_petrolcan`] = true, 14 | [`weapon_hazardcan`] = true, 15 | [`weapon_fireextinguisher`] = true, 16 | -- melee 17 | [`weapon_dagger`] = true, 18 | [`weapon_bat`] = true, 19 | [`weapon_bottle`] = true, 20 | [`weapon_crowbar`] = true, 21 | [`weapon_flashlight`] = true, 22 | [`weapon_golfclub`] = true, 23 | [`weapon_hammer`] = true, 24 | [`weapon_hatchet`] = true, 25 | [`weapon_knuckle`] = true, 26 | [`weapon_knife`] = true, 27 | [`weapon_machete`] = true, 28 | [`weapon_switchblade`] = true, 29 | [`weapon_nightstick`] = true, 30 | [`weapon_wrench`] = true, 31 | [`weapon_battleaxe`] = true, 32 | [`weapon_poolcue`] = true, 33 | [`weapon_briefcase`] = true, 34 | [`weapon_briefcase_02`] = true, 35 | [`weapon_garbagebag`] = true, 36 | [`weapon_handcuffs`] = true, 37 | [`weapon_bread`] = true, 38 | [`weapon_stone_hatchet`] = true, 39 | -- throwables 40 | [`weapon_grenade`] = true, 41 | [`weapon_bzgas`] = true, 42 | [`weapon_molotov`] = true, 43 | [`weapon_stickybomb`] = true, 44 | [`weapon_proxmine`] = true, 45 | [`weapon_snowball`] = true, 46 | [`weapon_pipebomb`] = true, 47 | [`weapon_ball`] = true, 48 | [`weapon_smokegrenade`] = true, 49 | [`weapon_flare`] = true 50 | } 51 | 52 | Config.WhitelistedWeaponStress = { -- Disable gaining stress from weapons in this table 53 | [`weapon_petrolcan`] = true, 54 | [`weapon_hazardcan`] = true, 55 | [`weapon_fireextinguisher`] = true 56 | } 57 | 58 | Config.VehClassStress = { -- Enable/Disable gaining stress from vehicle classes in this table 59 | ['0'] = true, -- Compacts 60 | ['1'] = true, -- Sedans 61 | ['2'] = true, -- SUVs 62 | ['3'] = true, -- Coupes 63 | ['4'] = true, -- Muscle 64 | ['5'] = true, -- Sports Classics 65 | ['6'] = true, -- Sports 66 | ['7'] = true, -- Super 67 | ['8'] = true, -- Motorcycles 68 | ['9'] = true, -- Off Road 69 | ['10'] = true, -- Industrial 70 | ['11'] = true, -- Utility 71 | ['12'] = true, -- Vans 72 | ['13'] = false, -- Cycles 73 | ['14'] = false, -- Boats 74 | ['15'] = false, -- Helicopters 75 | ['16'] = false, -- Planes 76 | ['18'] = false, -- Emergency 77 | ['19'] = false, -- Military 78 | ['20'] = false, -- Commercial 79 | ['21'] = false -- Trains 80 | } 81 | 82 | Config.WhitelistedVehicles = { -- Disable gaining stress from speeding in any vehicle in this table 83 | --[`adder`] = true 84 | } 85 | 86 | Config.WhitelistedJobs = { -- Disable stress completely for players with matching job or job type 87 | ['leo'] = true, 88 | ['ambulance'] = true 89 | } 90 | 91 | Config.Intensity = { 92 | ['blur'] = { 93 | [1] = { 94 | min = 50, 95 | max = 60, 96 | intensity = 1500, 97 | }, 98 | [2] = { 99 | min = 60, 100 | max = 70, 101 | intensity = 2000, 102 | }, 103 | [3] = { 104 | min = 70, 105 | max = 80, 106 | intensity = 2500, 107 | }, 108 | [4] = { 109 | min = 80, 110 | max = 90, 111 | intensity = 2700, 112 | }, 113 | [5] = { 114 | min = 90, 115 | max = 100, 116 | intensity = 3000, 117 | }, 118 | } 119 | } 120 | 121 | Config.EffectInterval = { 122 | [1] = { 123 | min = 50, 124 | max = 60, 125 | timeout = math.random(50000, 60000) 126 | }, 127 | [2] = { 128 | min = 60, 129 | max = 70, 130 | timeout = math.random(40000, 50000) 131 | }, 132 | [3] = { 133 | min = 70, 134 | max = 80, 135 | timeout = math.random(30000, 40000) 136 | }, 137 | [4] = { 138 | min = 80, 139 | max = 90, 140 | timeout = math.random(20000, 30000) 141 | }, 142 | [5] = { 143 | min = 90, 144 | max = 100, 145 | timeout = math.random(15000, 20000) 146 | } 147 | } 148 | 149 | Config.Menu = { 150 | isOutMapChecked = false, -- isOutMapChecked 151 | isOutCompassChecked = false, -- isOutMapChecked 152 | isCompassFollowChecked = true, -- isCompassFollowChecked 153 | isOpenMenuSoundsChecked = true, -- isOpenMenuSoundsChecked 154 | isResetSoundsChecked = true, -- isResetSoundsChecked 155 | isListSoundsChecked = true, -- isListSoundsChecked 156 | isMapNotifChecked = true, -- isMapNotifChecked 157 | isLowFuelChecked = true, -- isLowFuelChecked 158 | isCinematicNotifChecked = true, -- isCinematicNotifChecked 159 | isDynamicHealthChecked = true, -- isDynamicHealthChecked 160 | isDynamicArmorChecked = true, -- isDynamicArmorChecked 161 | isDynamicHungerChecked = true, -- isDynamicHungerChecked 162 | isDynamicThirstChecked = true, -- isDynamicThirstChecked 163 | isDynamicStressChecked = true, -- isDynamicStressChecked 164 | isDynamicOxygenChecked = true, -- isDynamicOxygenChecked 165 | isChangeFPSChecked = true, -- isChangeFPSChecked 166 | isHideMapChecked = false, -- isHideMapChecked 167 | isToggleMapBordersChecked = true, -- isToggleMapBordersChecked 168 | isDynamicEngineChecked = true, -- isDynamicEngineChecked 169 | isDynamicNitroChecked = true, -- isDynamicNitroChecked 170 | isChangeCompassFPSChecked = true, -- isChangeCompassFPSChecked 171 | isCompassShowChecked = true, -- isShowCompassChecked 172 | isShowStreetsChecked = true, -- isShowStreetsChecked 173 | isPointerShowChecked = true, -- isPointerShowChecked 174 | isDegreesShowChecked = true, -- isDegreesShowChecked 175 | isCinematicModeChecked = false, -- isCinematicModeChecked 176 | isToggleMapShapeChecked = 'square', -- isToggleMapShapeChecked 177 | } 178 | -------------------------------------------------------------------------------- /html/styles.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Work+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"); 2 | @import url("https://fonts.cdnfonts.com/css/pricedown"); 3 | @import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"); 4 | @import url("https://fonts.googleapis.com/css2?family=Yantramanav:wght@100;300;400;500;700;900&display=swap"); 5 | @import url("https://fonts.googleapis.com/css2?family=Work+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Yantramanav:wght@100;300;400;500;700;900&display=swap"); 6 | 7 | /* Menu */ 8 | div#openmenu { 9 | display: none; 10 | position: absolute; 11 | width: 50%; 12 | top: 45%; 13 | left: 50%; 14 | transform: translate(-50%, -50%); 15 | } 16 | .brand-logo { 17 | width: 25%; 18 | } /* when using an svg all you need to change is the width and it will resize it */ 19 | 20 | /* Menu tab & panel styles */ 21 | .text-tabcolor { 22 | color: rgb(255, 255, 255) !important; 23 | } 24 | .bg-active-tab { 25 | background: rgb(23 23 23) !important; 26 | } 27 | .bg-panel { 28 | background: rgb(30 30 30) !important; 29 | } 30 | .q-tab-panels { 31 | border-top-right-radius: 12px !important; 32 | border-bottom-right-radius: 12px !important; 33 | } /* change all 12px for a different border radius (rounds edges of the menu) */ 34 | .q-splitter__panel.q-splitter__before { 35 | border-top-left-radius: 12px !important; 36 | border-bottom-left-radius: 12px !important; 37 | } /* change all 12px for a different border radius (rounds edges of the menu) */ 38 | .q-tabs--vertical.q-tabs--not-scrollable .q-tabs__content { 39 | border-top-left-radius: 12px !important; 40 | border-bottom-left-radius: 12px !important; 41 | } /* change all 12px for a different border radius (rounds edges of the menu) */ 42 | 43 | /* Menu text styles */ 44 | .text-h6 { 45 | color: rgb(255, 255, 255) !important; 46 | } 47 | .text-h7 { 48 | color: rgba(255, 255, 255, 0.8) !important; 49 | } 50 | 51 | /* Menu buttons & checkboxes & toggle switch icons styles */ 52 | .text-textbutton { 53 | color: rgb(0, 0, 0) !important; 54 | } 55 | .bg-bgbutton { 56 | background: rgb(220 20 60) !important; 57 | } 58 | .q-checkbox__inner { 59 | color: rgb(255 255 255 / 70%) !important; 60 | } 61 | .text-checkbox { 62 | color: rgb(220 20 60) !important; 63 | } 64 | .q-checkbox__svg { 65 | color: rgb(0, 0, 0) !important; 66 | } 67 | .q-checkbox__inner--truthy .q-checkbox__bg { 68 | box-shadow: 0px 0px 3px 3px rgb(220 20 60 / 15%) !important; 69 | } /* if you want the checkboxes to have a glow/shadow */ 70 | .text-toggleicons { 71 | color: rgb(0, 0, 0) !important; 72 | } 73 | 74 | /* Menu misc */ 75 | hr { 76 | opacity: 0.1 !important; 77 | } /* horizontal line that seperates sections */ 78 | .q-mb-md { 79 | margin-bottom: 0px !important; 80 | } /* removes extra top padding */ 81 | .q-mb-md-d { 82 | padding-left: 10px !important; 83 | padding-bottom: 10px !important; 84 | } /* keeps q-items aligned */ 85 | .q-item { 86 | padding: 8px 0px !important; 87 | } /* keeps q-items aligned */ 88 | .q-item__section--avatar { 89 | min-width: 40px !important; 90 | } /* keeps q-items aligned */ 91 | .q-item__section--side { 92 | padding-right: 0px !important; 93 | } /* keeps q-items aligned */ 94 | .q-splitter--vertical > .q-splitter__separator { 95 | width: 0px !important; 96 | } /* keeps navigation tab panel seamless */ 97 | div#q-loading-bar { 98 | display: none !important; 99 | } /* makes sure there's no ajax load from quasar */ 100 | ::-webkit-scrollbar { 101 | display: none !important; 102 | } /* makes sure there's no ugly scrollbar on menu*/ 103 | 104 | /* Hud radial styles */ 105 | .text-health { 106 | color: rgb(33, 171, 97) !important; 107 | } 108 | .text-stress { 109 | color: rgb(255, 0, 0) !important; 110 | } 111 | .text-nos { 112 | color: rgb(255, 72, 133) !important; 113 | } 114 | .text-cruise { 115 | color: rgb(255, 72, 133) !important; 116 | } 117 | .text-armed { 118 | color: rgb(255, 72, 133) !important; 119 | } 120 | .text-harness { 121 | color: rgb(182, 72, 255) !important; 122 | } 123 | .text-oxygen { 124 | color: rgb(138, 168, 189) !important; 125 | } 126 | .text-parachute { 127 | color: rgb(0, 0, 0) !important; 128 | } 129 | .text-dev { 130 | color: rgb(0, 0, 0) !important; 131 | } 132 | .text-gauge { 133 | color: rgb(255, 255, 255) !important; 134 | } 135 | 136 | #main-container { 137 | width: 100%; 138 | height: auto; 139 | } 140 | 141 | /* Money */ 142 | #money-container { 143 | position: absolute; 144 | right: 2vw; 145 | top: 5vh; 146 | font-weight: 400; 147 | font-size: 40px; 148 | } 149 | 150 | #sign, 151 | #bank { 152 | font-family: "Pricedown Bl", sans-serif; 153 | text-align: right; 154 | color: #00ac31; 155 | text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.7), 1px -1px 0 rgba(0, 0, 0, 0.7), -1px 1px 0 rgba(0, 0, 0, 0.7), 1px 1px 0 rgba(0, 0, 0, 0.7); 156 | } 157 | 158 | #plus { 159 | font-size: 50px; 160 | font-family: "Pricedown Bl", sans-serif; 161 | text-align: right; 162 | color: #00ac31; 163 | text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.7), 1px -1px 0 rgba(0, 0, 0, 0.7), -1px 1px 0 rgba(0, 0, 0, 0.7), 1px 1px 0 rgba(0, 0, 0, 0.7); 164 | } 165 | 166 | #minus { 167 | font-size: 50px; 168 | font-family: "Pricedown Bl", sans-serif; 169 | text-align: right; 170 | color: #ac0000; 171 | text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.7), 1px -1px 0 rgba(0, 0, 0, 0.7), -1px 1px 0 rgba(0, 0, 0, 0.7), 1px 1px 0 rgba(0, 0, 0, 0.7); 172 | } 173 | 174 | #money { 175 | font-family: "Pricedown Bl", sans-serif; 176 | text-align: right; 177 | color: #ffffff; 178 | text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.7), 1px -1px 0 rgba(0, 0, 0, 0.7), -1px 1px 0 rgba(0, 0, 0, 0.7), 1px 1px 0 rgba(0, 0, 0, 0.7); 179 | } 180 | 181 | /* Player HUD */ 182 | 183 | #playerhud { 184 | position: absolute; 185 | display: flex; 186 | left: 3vh; 187 | bottom: 0.2vw; 188 | } 189 | 190 | .q-ml-xl { 191 | margin-left: -22px !important; /* Change this to space radials */ 192 | } 193 | 194 | /* Vehicle HUD */ 195 | 196 | speed:after { 197 | content: "MPH"; /* If using KPH change this content from MPH */ 198 | display: block; 199 | padding-top: 3px; 200 | padding-left: 2px; 201 | padding-right: 2px; 202 | padding-bottom: 8px; 203 | font-weight: 900; 204 | } 205 | 206 | altitude:after { 207 | content: "ALT"; 208 | display: block; 209 | padding-top: 10px; 210 | padding-left: 2px; 211 | padding-right: 2px; 212 | font-weight: 900; 213 | } 214 | 215 | speed { 216 | transform: rotate(150deg); 217 | font-size: 2.4vh; 218 | position: fixed; 219 | color: #fff; 220 | text-align: center; 221 | font-weight: 600; 222 | text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.7), 1px -1px 0 rgba(0, 0, 0, 0.7), -1px 1px 0 rgba(0, 0, 0, 0.7), 1px 1px 0 rgba(0, 0, 0, 0.7); 223 | } 224 | 225 | altitude { 226 | transform: rotate(135deg); 227 | font-size: 2.4vh; 228 | position: fixed; 229 | color: #fff; 230 | text-align: center; 231 | font-weight: 600; 232 | text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.7), 1px -1px 0 rgba(0, 0, 0, 0.7), -1px 1px 0 rgba(0, 0, 0, 0.7), 1px 1px 0 rgba(0, 0, 0, 0.7); 233 | } 234 | 235 | .border { 236 | bottom: 7.9%; 237 | left: 1.3%; 238 | width: 0%; 239 | text-align: center; 240 | } 241 | 242 | .square { 243 | bottom: 6.3%; 244 | width: 29vh; 245 | height: 18.5vh; 246 | border: 4px solid #bababa; 247 | position: absolute; 248 | display: inline-block; 249 | } 250 | 251 | .circle { 252 | bottom: 6.9%; 253 | width: 27vh; 254 | height: 22.9vh; 255 | border: 4px solid #bababa; 256 | position: absolute; 257 | display: inline-block; 258 | border-radius: 50%; 259 | } 260 | 261 | /* Animation */ 262 | .slide-fade-enter-active { 263 | transition: all 0.3s ease-out; 264 | } 265 | 266 | .slide-fade-leave-active { 267 | transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1); 268 | } 269 | 270 | .slide-fade-enter-from, 271 | .slide-fade-leave-to { 272 | transform: translateX(20px); 273 | opacity: 0; 274 | } 275 | 276 | .fade-enter-active, 277 | .fade-leave-active { 278 | transition: opacity 2s ease; 279 | } 280 | 281 | .fade-enter-from, 282 | .fade-leave-to { 283 | opacity: 0; 284 | } 285 | 286 | /* Compass */ 287 | .baseplate { 288 | position: relative; 289 | margin: 0 auto; 290 | top: -0.8vh; 291 | width: 150px; 292 | height: auto; 293 | } 294 | 295 | .street-container { 296 | position: relative; 297 | top: 0.5vh; 298 | font-family: Arial, Helvetica, sans-serif; 299 | font-size: 1.4vh; 300 | letter-spacing: 0.7px; 301 | text-decoration: none; 302 | font-style: normal; 303 | font-variant: small-caps; 304 | text-transform: none; 305 | font-weight: 800; 306 | text-shadow: 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6); 307 | } 308 | 309 | .street1 { 310 | position: absolute; 311 | margin: 0 auto; 312 | right: 55%; 313 | text-align: right !important; 314 | color: rgb(255, 255, 255); 315 | } 316 | 317 | .street2 { 318 | position: absolute; 319 | margin: 0 auto; 320 | left: 55%; 321 | text-align: left !important; 322 | color: rgb(255, 255, 255); 323 | } 324 | 325 | .pointer { 326 | position: absolute; 327 | margin: 0 auto; 328 | top: -2%; 329 | left: 0; 330 | right: 0; 331 | font-family: "Yantramanav", sans-serif; 332 | color: rgb(255, 255, 255); 333 | font-size: 2.2vh; 334 | text-align: center; 335 | text-shadow: 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6); 336 | z-index: 9999; 337 | } 338 | 339 | .degrees { 340 | position: absolute; 341 | margin: 0 auto; 342 | top: 80%; 343 | left: 0; 344 | right: 0; 345 | opacity: 0.8; 346 | font-family: "Yantramanav", sans-serif; 347 | color: rgb(255, 255, 255); 348 | font-size: 1.5vh; 349 | font-weight: 600; 350 | text-align: center; 351 | text-shadow: 0 0 1px rgb(0 0 0 / 60%), 0 0 1px rgb(0 0 0 / 60%), 0 0 1px rgb(0 0 0 / 60%), 0 0 1px rgb(0 0 0 / 60%); 352 | } 353 | 354 | .bezel { 355 | position: relative; 356 | width: 100%; 357 | height: 2vh; 358 | font-family: "Yantramanav", sans-serif; 359 | font-size: 0.35vh; 360 | font-weight: 700; 361 | text-shadow: 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6); 362 | } 363 | 364 | .bearing { 365 | position: relative; 366 | width: 100%; 367 | top: -0.5vh; 368 | height: 3.5vh; 369 | padding-left: 0.12vw; 370 | font-family: Arial, Helvetica, sans-serif; 371 | font-size: 2.3vh; 372 | letter-spacing: 0.7px; 373 | text-decoration: none; 374 | font-style: normal; 375 | font-variant: small-caps; 376 | text-transform: none; 377 | font-weight: 600; 378 | text-shadow: 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.6); 379 | } 380 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to QBCore 2 | 3 | First of all, thank you for taking the time to contribute! 4 | 5 | These guidelines will help you help us in the best way possible regardless of your skill level. We ask that you try to read everything related to the way you'd like to contribute and try and use your best judgement for anything not covered. 6 | 7 | ### Table of Contents 8 | 9 | [Code of Conduct](#code-of-conduct) 10 | 11 | [I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question) 12 | 13 | [How Can I Contribute?](#how-can-i-contribute) 14 | * [Reporting Bugs](#reporting-bugs) 15 | * [Suggesting Features / Enhancements](#suggesting-features--enhancements) 16 | * [Your First Code Contribution](#your-first-code-contribution) 17 | * [Pull Requests](#pull-requests) 18 | 19 | [Styleguides](#styleguides) 20 | * [Git Commit Messages](#git-commit-messages) 21 | * [Lua Styleguide](#lua-styleguide) 22 | * [JavaScript Styleguide](#javascript-styleguide) 23 | 24 | 25 | 26 | ## Code of Conduct 27 | 28 | - Refrain from using languages other than English. 29 | - Refrain from discussing any politically charged or inflammatory topics. 30 | - Uphold mature conversations and respect each other; excessive profanity, hate speech or any kind of harassment will not be tolerated. 31 | - No advertising of any kind. 32 | - Follow these guidelines. 33 | - Do not mention members of github unless a question is directed at them and can't be answered by anyone else. 34 | - Do not mention any of the development team for any reason. We will read things as we get to them. 35 | 36 | ## I don't want to read this whole thing I just have a question!!! 37 | 38 | > **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below. 39 | 40 | * [QBCore Website](https://qbcore.org) 41 | * [QBCore Discord](https://discord.gg/qbcore) 42 | * [FiveM Discord - #qbcore channel](https://discord.gg/fivem) 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ## How Can I Contribute? 54 | 55 | ### Reporting Bugs 56 | 57 | The easiest way to contribute for most people is just to report bugs you find cause if nobody reports it there's a chance we'll never know it exists and then we'll never fix it. 58 | 59 | Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out the bug-report template with the information it asks for helps us resolve issues faster. 60 | 61 | > **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. 62 | 63 | #### Before Submitting A Bug Report 64 | 65 | * **Check the docs** There's a chance what you see as a bug might just work differently than you expect and if you think it could work better consider a feature enhancement report instead. 66 | * **Search the [discord](https://discord.gg/qbcore)** to see if anyone else has run into the issue and see if it was solved through user error or code changes. (if the code change isn't pending a PR and you know what you're doing consider submitting one following [Pull Requests](#pull-requests) ) 67 | * **Determine which resource the problem should be reported in**. If the bug is related to the inventory for example report this bug under qb-inventory rather than under qb-core or some other resource. 68 | * **Perform a [cursory search](https://github.com/search?q=+is%3Aissue+user%3Aqbcore-framework)** to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one. 69 | 70 | #### How Do I Submit A (Good) Bug Report? 71 | 72 | Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined which resource your bug is related to, create an issue on that repository and provide the following information by filling in bug-report template. 73 | 74 | Explain the problem and include additional details to help maintainers reproduce the problem: 75 | 76 | * **Use a clear and descriptive title** for the issue to identify the problem. 77 | * **Describe the exact steps which reproduce the problem** in as many details as possible. 78 | * **Provide specific examples to demonstrate the steps**. If something happened with only a specific group or single item but not others, specify that. 79 | * **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. 80 | * **Explain which behavior you expected to see instead and why.** 81 | * **Include screenshots** which show the specific bug in action or before and after. 82 | * **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below. 83 | 84 | Provide more context by answering these questions if possible: 85 | 86 | * **Did the problem start happening recently** (e.g. after updating to a new version of QBCore?) or was this always a problem? 87 | * If the problem started happening recently, **can you reproduce the problem in an older version of QBCore?** What's the most recent commit in which the problem doesn't happen? 88 | * **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens. 89 | 90 | Include details about your setup: 91 | 92 | * **When was your QBCore last updated?** 93 | * **What OS is the server running on**? 94 | * **Which *extra* resources do you have installed?** 95 | 96 | 97 | --- 98 | 99 | 100 | ### Suggesting Features / Enhancements 101 | 102 | This section guides you through submitting an enhancement suggestion for QBCore, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion. 103 | 104 | Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in feature request template, including the steps that you imagine you would take if the feature you're requesting existed. 105 | 106 | #### Before Submitting An Enhancement Suggestion 107 | 108 | * **Make sure it doesn't already exist.** Sounds silly, but there's a lot of features built in to qbcore that people don't realize so take a look through the docs and stuff to make sure it's not already there. 109 | * **Check if there's already PR which provides that enhancement.** 110 | * **Determine which resource the enhancement should be suggested in.** if it fits with another resource suggest it in that resource. if it would be it's own resource suggest it in the main qb-core repository. 111 | * **Perform a [cursory search](https://github.com/search?q=+is%3Aissue+user%3Aqbcore-framework)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. 112 | 113 | #### How Do I Submit A (Good) Enhancement Suggestion? 114 | 115 | Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined which resource your enhancement suggestion is related to, create an issue on that repository and provide the following information: 116 | 117 | * **Use a clear and descriptive title** for the issue to identify the suggestion. 118 | * **Provide a step-by-step description of the suggested enhancement** in as many details as possible. 119 | * **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). 120 | * **Describe the current behavior** and **explain which behavior you expected to see instead** and why. 121 | * **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of QBCore which the suggestion is related to. 122 | * **Explain why this enhancement would be useful.** 123 | * **Be creative and unique.** Stealing ideas from popular servers 1:1 detail isn't going to get accepted. 124 | 125 | 126 | --- 127 | 128 | 129 | 130 | ### Your First Code Contribution 131 | 132 | Unsure where to begin contributing to QBCore? You can start by looking through these `beginner` and `help-wanted` issues. 133 | 134 | 135 | 136 | --- 137 | 138 | 139 | ### Pull Requests 140 | 141 | The process described here has several goals: 142 | 143 | - Maintain QBCore's quality. 144 | - Fix problems that are important to users. 145 | - Engage the community in working toward the best possible QBCore. 146 | - Enable a sustainable system for QBCore's maintainers to review contributions. 147 | 148 | Please follow these steps to have your contribution considered by the maintainers: 149 | 150 | 1. Follow all instructions in The Pull Request template. 151 | 2. Follow the [styleguides](#styleguides). 152 | 3. Await review by the reviewer(s). 153 | 154 | While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted. 155 | 156 | 157 | --- 158 | 159 | ## Styleguides 160 | 161 | ### Git Commit Messages 162 | 163 | * Limit the first line to 72 characters or less. 164 | * Reference issues and pull requests liberally after the first line. 165 | * Consider starting the commit message with an applicable emoji: 166 | * :art: `:art:` when improving the format/structure of the code 167 | * :racehorse: `:racehorse:` when improving performance 168 | * :memo: `:memo:` when writing docs 169 | * :bug: `:bug:` when fixing a bug 170 | * :fire: `:fire:` when removing code or files 171 | * :white_check_mark: `:white_check_mark:` when adding tests 172 | * :lock: `:lock:` when dealing with security 173 | * :arrow_up: `:arrow_up:` when upgrading dependencies 174 | * :arrow_down: `:arrow_down:` when downgrading dependencies 175 | * :shirt: `:shirt:` when removing linter warnings 176 | 177 | ### Lua Styleguide 178 | 179 | All lua code should be done using all the best practices of proper lua using the easiest to read yet fastest/most optimized methods of execution. 180 | 181 | - Use 4 Space indentation 182 | - Aim for lua 5.4 (include `lua54 'yes'` in the fxmanifest.lua) 183 | - Use `PlayerPedId()` instead of `GetPlayerPed(-1)` 184 | - Use `#(vector3 - vector3)` instead of `GetDistanceBetweenCoords()` 185 | - Don't create unnecessary threads. always try to find a better method of triggering events 186 | - Don't repeat yourself.. if you're using the same operations in many different places convert them into a function with flexible variables 187 | - For distance checking loops set longer waits if you're outside of a range 188 | - Job specific loops should only run for players with that job, don't waste cycles 189 | - When possible don't trust the client, esspecially with transactions 190 | - Balance security and optimizations 191 | - [Consider this Lua Performance guide](https://springrts.com/wiki/Lua_Performance) 192 | - Use local varriables everywhere possible 193 | - Make use of config options where it makes sense making features optional or customizable 194 | - Instead of `table.insert(myTable, "Value")` use `myTable[#myTable + 1] = "Value"` 195 | - Instead of `table.insert(ages, "bob", 30)` use `ages["bob"] = 30` 196 | 197 | 198 | ### JavaScript Styleguide 199 | 200 | - Use 4 Space indentation 201 | - Don't repeat yourself.. if you're using the same operations in many different places convert them into a function with flexible variables. 202 | -------------------------------------------------------------------------------- /html/responsive.css: -------------------------------------------------------------------------------- 1 | .responsive { 2 | position: absolute !important; 3 | } 4 | 5 | @media (min-width: 800px) { 6 | .responsive { 7 | margin-left: 32vh !important; 8 | transform: scale(1, 1); 9 | bottom: 6.9vh !important; 10 | } 11 | .q-ml-xl { 12 | font-size: 50px; 13 | } 14 | #Speedo { 15 | font-size: 70px !important; 16 | } 17 | #FuelGaugeBackground { 18 | font-size: 36px; 19 | } 20 | #FuelGaugeValue { 21 | font-size: 36px; 22 | } 23 | #FuelGaugeIcon { 24 | font-size: 14px; 25 | } 26 | #Icons { 27 | font-size: 19.5px; 28 | } 29 | #speedometer { 30 | position: relative; 31 | left: 2.5vh !important; 32 | } 33 | #fuelgauge { 34 | position: relative; 35 | left: 7vh !important; 36 | bottom: 6.7vh !important; 37 | } 38 | #altitudegauge { 39 | position: relative; 40 | left: 11vh !important; 41 | } 42 | #seatbelt { 43 | position: relative; 44 | left: 8.5vh !important; 45 | } 46 | speed { 47 | font-size: 2vh !important; 48 | } 49 | speed:after { 50 | font-size: 0.9vh !important; 51 | } 52 | altitude { 53 | font-size: 2vh !important; 54 | } 55 | altitude:after { 56 | font-size: 0.9vh !important; 57 | } 58 | .square { 59 | left: 2.5vh !important; 60 | bottom: 6% !important; 61 | } 62 | .circle { 63 | left: 3.2vh !important; 64 | width: 27.6vh !important; 65 | bottom: 6.9% !important; 66 | } 67 | } 68 | 69 | @media (width: 3840px) and (height: 2160px) { 70 | .responsive { 71 | margin-left: 32.8vh !important; 72 | transform: scale(1.3, 1.3); 73 | bottom: 7.6vh !important; 74 | } 75 | .q-ml-xl { 76 | font-size: 100px; 77 | margin-left: -45px !important; /* Change this to space radials */ 78 | } 79 | #Speedo { 80 | font-size: 125px !important; 81 | } 82 | #Speed { 83 | font-size: 50px !important; 84 | } 85 | #FuelGaugeBackground { 86 | font-size: 75px !important; 87 | left: 50% !important; 88 | top: 20px !important; 89 | } 90 | #FuelGaugeValue { 91 | font-size: 75px !important; 92 | left: 0% !important; 93 | top: 20px !important; 94 | } 95 | #FuelGaugeIcon { 96 | font-size: 25px; 97 | } 98 | #Altimeter { 99 | font-size: 125px !important; 100 | left: 41% !important; 101 | } 102 | #AltimeterValue { 103 | font-size: 125px !important; 104 | left: -9% !important; 105 | } 106 | #Alt { 107 | font-size: 50px !important; 108 | } 109 | #Icons { 110 | font-size: 50px; 111 | } 112 | #SeatbeltLocation { 113 | left: 35% !important; 114 | top: -40px; 115 | } 116 | #SeatbeltIcon { 117 | font-size: 40px !important; 118 | } 119 | #speedometer { 120 | position: relative; 121 | left: 2.5vh !important; 122 | } 123 | #fuelgauge { 124 | position: relative; 125 | left: 5.3vh !important; 126 | bottom: 7.1vh !important; 127 | } 128 | #altitudegauge { 129 | position: relative; 130 | left: 8.2vh !important; 131 | } 132 | #seatbelt { 133 | position: relative; 134 | left: 6.5vh !important; 135 | } 136 | speed { 137 | font-size: 1.2vh !important; 138 | } 139 | speed:after { 140 | font-size: 0.6vh !important; 141 | } 142 | altitude { 143 | font-size: 1.2vh !important; 144 | } 145 | altitude:after { 146 | font-size: 0.6vh !important; 147 | } 148 | .square { 149 | left: 2.4vh !important; 150 | bottom: 6.1% !important; 151 | width: 29.3vh !important; 152 | } 153 | .circle { 154 | left: 3.6vh !important; 155 | width: 27.6vh !important; 156 | bottom: 6.9% !important; 157 | } 158 | } 159 | 160 | @media (width: 3440px) and (height: 1440px) { 161 | .responsive { 162 | margin-left: 33vh !important; 163 | transform: scale(1.3, 1.3); 164 | bottom: 7.6vh !important; 165 | } 166 | .q-ml-xl { 167 | font-size: 50px; 168 | } 169 | #Speedo { 170 | font-size: 70px !important; 171 | } 172 | #FuelGaugeBackground { 173 | font-size: 36px; 174 | } 175 | #FuelGaugeValue { 176 | font-size: 36px; 177 | } 178 | #FuelGaugeIcon { 179 | font-size: 14px; 180 | } 181 | #Icons { 182 | font-size: 19.5px; 183 | } 184 | #speedometer { 185 | position: relative; 186 | left: 2.5vh !important; 187 | } 188 | #fuelgauge { 189 | position: relative; 190 | left: 6.4vh !important; 191 | bottom: 6.85vh !important; 192 | } 193 | #altitudegauge { 194 | position: relative; 195 | left: 11.2vh !important; 196 | } 197 | #seatbelt { 198 | position: relative; 199 | left: 8.8vh !important; 200 | } 201 | speed { 202 | font-size: 1.4vh !important; 203 | } 204 | speed:after { 205 | font-size: 0.7vh !important; 206 | } 207 | altitude { 208 | font-size: 1.4vh !important; 209 | } 210 | altitude:after { 211 | font-size: 0.7vh !important; 212 | } 213 | .square { 214 | left: 2.3vh !important; 215 | bottom: 6.1% !important; 216 | width: 29.3vh !important; 217 | } 218 | .circle { 219 | left: 3.5vh !important; 220 | width: 27.6vh !important; 221 | bottom: 6.9% !important; 222 | } 223 | } 224 | 225 | @media (width: 2560px) and (height: 1440px) { 226 | .responsive { 227 | margin-left: 33.5vh !important; 228 | transform: scale(1.3, 1.3); 229 | bottom: 7.2vh !important; 230 | } 231 | .q-ml-xl { 232 | font-size: 50px; 233 | } 234 | #Speedo { 235 | font-size: 70px !important; 236 | } 237 | #FuelGaugeBackground { 238 | font-size: 36px; 239 | } 240 | #FuelGaugeValue { 241 | font-size: 36px; 242 | } 243 | #FuelGaugeIcon { 244 | font-size: 14px; 245 | } 246 | #Icons { 247 | font-size: 19.5px; 248 | } 249 | #speedometer { 250 | position: relative; 251 | left: 2.5vh !important; 252 | } 253 | #fuelgauge { 254 | position: relative; 255 | left: 6.3vh !important; 256 | bottom: 6.5vh !important; 257 | } 258 | #altitudegauge { 259 | position: relative; 260 | left: 11vh !important; 261 | } 262 | #seatbelt { 263 | position: relative; 264 | left: 8.8vh !important; 265 | } 266 | speed { 267 | font-size: 1.4vh !important; 268 | } 269 | speed:after { 270 | font-size: 0.7vh !important; 271 | } 272 | altitude { 273 | font-size: 1.4vh !important; 274 | } 275 | altitude:after { 276 | font-size: 0.7vh !important; 277 | } 278 | .square { 279 | left: 2.3vh !important; 280 | bottom: 6% !important; 281 | } 282 | .circle { 283 | left: 3.5vh !important; 284 | width: 27.6vh !important; 285 | bottom: 6.7% !important; 286 | } 287 | } 288 | 289 | @media (width: 2560px) and (height: 1080px) { 290 | #speedometer { 291 | position: relative; 292 | left: 2.5vh !important; 293 | } 294 | #fuelgauge { 295 | position: relative; 296 | left: 6.5vh !important; 297 | bottom: 5.7vh !important; 298 | } 299 | #seatbelt { 300 | position: relative; 301 | left: 6.5vh !important; 302 | } 303 | .square { 304 | left: 2.5vh !important; 305 | bottom: 6% !important; 306 | } 307 | .circle { 308 | left: 3.2vh !important; 309 | width: 27.6vh !important; 310 | bottom: 6.9% !important; 311 | } 312 | } 313 | 314 | @media (width: 1920px) and (height: 1440px) { 315 | .responsive { 316 | margin-left: 32vh !important; 317 | transform: scale(1.2, 1.2); 318 | bottom: 7.4vh !important; 319 | } 320 | .q-ml-xl { 321 | font-size: 50px; 322 | } 323 | #Speedo { 324 | font-size: 70px !important; 325 | } 326 | #FuelGaugeBackground { 327 | font-size: 36px; 328 | } 329 | #FuelGaugeValue { 330 | font-size: 36px; 331 | } 332 | #FuelGaugeIcon { 333 | font-size: 14px; 334 | } 335 | #Icons { 336 | font-size: 19.5px; 337 | } 338 | #speedometer { 339 | position: relative; 340 | left: 2.5vh !important; 341 | } 342 | #fuelgauge { 343 | position: relative; 344 | left: 6.3vh !important; 345 | bottom: 6.9vh !important; 346 | } 347 | #altitudegauge { 348 | position: relative; 349 | left: 10vh !important; 350 | } 351 | #seatbelt { 352 | position: relative; 353 | left: 8vh !important; 354 | } 355 | speed { 356 | font-size: 1.6vh !important; 357 | } 358 | speed:after { 359 | font-size: 0.7vh !important; 360 | } 361 | altitude { 362 | font-size: 1.6vh !important; 363 | } 364 | altitude:after { 365 | font-size: 0.7vh !important; 366 | } 367 | .square { 368 | left: 2vh !important; 369 | bottom: 6% !important; 370 | } 371 | .circle { 372 | left: 2.7vh !important; 373 | width: 27.6vh !important; 374 | bottom: 7% !important; 375 | } 376 | } 377 | 378 | @media (width: 1920px) and (height: 1200px) { 379 | .responsive { 380 | margin-left: 31.5vh !important; 381 | transform: scale(1, 1); 382 | bottom: 6.4vh !important; 383 | } 384 | .q-ml-xl { 385 | font-size: 50px; 386 | } 387 | #Speedo { 388 | font-size: 70px !important; 389 | } 390 | #FuelGaugeBackground { 391 | font-size: 36px; 392 | } 393 | #FuelGaugeValue { 394 | font-size: 36px; 395 | } 396 | #FuelGaugeIcon { 397 | font-size: 14px; 398 | } 399 | #Icons { 400 | font-size: 19.5px; 401 | } 402 | #speedometer { 403 | position: relative; 404 | left: 2.5vh !important; 405 | } 406 | #fuelgauge { 407 | position: relative; 408 | left: 6.6vh !important; 409 | bottom: 6.05vh !important; 410 | } 411 | #altitudegauge { 412 | position: relative; 413 | left: 10vh !important; 414 | } 415 | #seatbelt { 416 | position: relative; 417 | left: 8vh !important; 418 | } 419 | speed { 420 | font-size: 1.8vh !important; 421 | } 422 | speed:after { 423 | font-size: 0.8vh !important; 424 | } 425 | altitude { 426 | font-size: 1.8vh !important; 427 | } 428 | altitude:after { 429 | font-size: 0.8vh !important; 430 | } 431 | .square { 432 | left: 2.2vh !important; 433 | bottom: 6% !important; 434 | } 435 | .circle { 436 | left: 3.2vh !important; 437 | width: 27.6vh !important; 438 | bottom: 7% !important; 439 | } 440 | } 441 | 442 | @media (width: 1920px) and (height: 1080px) { 443 | .responsive { 444 | margin-left: 32vh !important; 445 | transform: scale(1, 1); 446 | bottom: 6.9vh !important; 447 | } 448 | .q-ml-xl { 449 | font-size: 50px; 450 | } 451 | #Speedo { 452 | font-size: 70px !important; 453 | } 454 | #FuelGaugeBackground { 455 | font-size: 36px; 456 | } 457 | #FuelGaugeValue { 458 | font-size: 36px; 459 | } 460 | #FuelGaugeIcon { 461 | font-size: 14px; 462 | } 463 | #Icons { 464 | font-size: 19.5px; 465 | } 466 | #speedometer { 467 | position: relative; 468 | left: 2.5vh !important; 469 | } 470 | #fuelgauge { 471 | position: relative; 472 | left: 7.2vh !important; 473 | bottom: 6.6vh !important; 474 | } 475 | #altitudegauge { 476 | position: relative; 477 | left: 11vh !important; 478 | } 479 | #seatbelt { 480 | position: relative; 481 | left: 8.5vh !important; 482 | } 483 | speed { 484 | font-size: 2vh !important; 485 | } 486 | speed:after { 487 | font-size: 1.2vh !important; 488 | } 489 | altitude { 490 | font-size: 2vh !important; 491 | } 492 | altitude:after { 493 | font-size: 0.9vh !important; 494 | } 495 | .square { 496 | left: 2.5vh !important; 497 | bottom: 6% !important; 498 | } 499 | .circle { 500 | left: 3.7vh !important; 501 | width: 27.3vh !important; 502 | bottom: 7% !important; 503 | } 504 | } 505 | 506 | @media (width: 1280px) and (height: 720px) { 507 | .responsive { 508 | margin-left: 30vh !important; 509 | transform: scale(0.65, 0.65); 510 | bottom: 4.7vh !important; 511 | } 512 | .q-ml-xl { 513 | font-size: 50px; 514 | } 515 | #Speedo { 516 | font-size: 70px !important; 517 | } 518 | #FuelGaugeBackground { 519 | font-size: 36px; 520 | } 521 | #FuelGaugeValue { 522 | font-size: 36px; 523 | } 524 | #FuelGaugeIcon { 525 | font-size: 14px; 526 | } 527 | #Icons { 528 | font-size: 19.5px; 529 | } 530 | #speedometer { 531 | position: relative; 532 | left: 2.5vh !important; 533 | } 534 | #fuelgauge { 535 | position: relative; 536 | left: 8.6vh !important; 537 | bottom: 5.2vh !important; 538 | } 539 | #altitudegauge { 540 | position: relative; 541 | left: 11vh !important; 542 | } 543 | #seatbelt { 544 | position: relative; 545 | left: 8.5vh !important; 546 | } 547 | speed { 548 | font-size: 3vh !important; 549 | } 550 | speed:after { 551 | font-size: 1.4vh !important; 552 | } 553 | altitude { 554 | font-size: 3vh !important; 555 | } 556 | altitude:after { 557 | font-size: 1.4vh !important; 558 | } 559 | .square { 560 | left: 2.5vh !important; 561 | bottom: 6% !important; 562 | } 563 | .circle { 564 | left: 4vh !important; 565 | width: 27.6vh !important; 566 | bottom: 6.9% !important; 567 | } 568 | } 569 | -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
{{street2}}
18 |
{{street1}}
19 |
20 |
21 |
˅
22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | N 41 | N 42 | NW 43 | NW 44 | NE 45 | NE 46 | E 47 | SE 48 | S 49 | SW 50 | W 51 | 52 |
53 |
54 |
55 | 192 |
193 |
194 |
195 |
196 | 197 |

{{(cash)}}

198 |
199 |
200 |
201 | 202 |

{{(bank)}}

203 |
204 |
205 |
206 |

{{(amount)}}

207 |

{{(amount)}}

208 |
209 |
210 |
211 |
212 | 213 |
214 | 215 | 216 | 217 |
218 |
219 | 220 |
221 | 222 | 223 | 224 |
225 |
226 | 227 |
228 | 229 | 230 | 231 |
232 |
233 | 234 |
235 | 236 | 237 | 238 |
239 |
240 | 241 |
242 | 243 | 244 | 245 |
246 |
247 | 248 |
249 | 250 | 251 | 252 |
253 |
254 | 255 |
256 | 257 | 258 | 259 |
260 |
261 | 262 |
263 | 264 | 265 | 266 |
267 |
268 | 269 |
270 | 271 | 272 | 273 |
274 |
275 | 276 |
277 | 278 | 279 | 280 |
281 |
282 | 283 |
284 | 285 | 286 | 287 |
288 |
289 | 290 |
291 | 292 | 293 | 294 |
295 |
296 | 297 |
298 | 299 | 300 | 301 |
302 |
303 | 304 |
305 | 306 | 307 | 308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 | 316 | 317 | {{(speed)}} 318 |
319 |
320 | 321 | 322 | 323 |
324 |
325 | 326 | 327 | {{(altitude)}} 328 |
329 | 330 |
331 | 332 | 333 | 334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 | 346 | 347 | -------------------------------------------------------------------------------- /client.lua: -------------------------------------------------------------------------------- 1 | local QBCore = exports['qb-core']:GetCoreObject() 2 | local PlayerData = QBCore.Functions.GetPlayerData() 3 | local config = Config 4 | local speedMultiplier = config.UseMPH and 2.23694 or 3.6 5 | local seatbeltOn = false 6 | local cruiseOn = false 7 | local showAltitude = false 8 | local showSeatbelt = false 9 | local nos = 0 10 | local stress = 0 11 | local hunger = 100 12 | local thirst = 100 13 | local cashAmount = 0 14 | local bankAmount = 0 15 | local nitroActive = 0 16 | local harness = 0 17 | local hp = 100 18 | local armed = 0 19 | local parachute = -1 20 | local oxygen = 100 21 | local dev = false 22 | local playerDead = false 23 | local showMenu = false 24 | local showCircleB = false 25 | local showSquareB = false 26 | local Menu = config.Menu 27 | local CinematicHeight = 0.2 28 | local w = 0 29 | local radioActive = false 30 | 31 | DisplayRadar(false) 32 | 33 | local function CinematicShow(bool) 34 | SetBigmapActive(true, false) 35 | Wait(0) 36 | SetBigmapActive(false, false) 37 | if bool then 38 | for i = CinematicHeight, 0, -1.0 do 39 | Wait(10) 40 | w = i 41 | end 42 | else 43 | for i = 0, CinematicHeight, 1.0 do 44 | Wait(10) 45 | w = i 46 | end 47 | end 48 | end 49 | 50 | local function loadSettings(settings) 51 | for k, v in pairs(settings) do 52 | if k == 'isToggleMapShapeChecked' then 53 | Menu.isToggleMapShapeChecked = v 54 | SendNUIMessage({ test = true, event = k, toggle = v }) 55 | elseif k == 'isCinematicModeChecked' then 56 | Menu.isCinematicModeChecked = v 57 | CinematicShow(v) 58 | SendNUIMessage({ test = true, event = k, toggle = v }) 59 | elseif k == 'isChangeFPSChecked' then 60 | Menu[k] = v 61 | local val = v and 'Optimized' or 'Synced' 62 | SendNUIMessage({ test = true, event = k, toggle = val }) 63 | else 64 | Menu[k] = v 65 | SendNUIMessage({ test = true, event = k, toggle = v }) 66 | end 67 | end 68 | QBCore.Functions.Notify(Lang:t('notify.hud_settings_loaded'), 'success') 69 | Wait(1000) 70 | TriggerEvent('hud:client:LoadMap') 71 | end 72 | 73 | local function saveSettings() 74 | SetResourceKvp('hudSettings', json.encode(Menu)) 75 | end 76 | 77 | local function hasHarness(items) 78 | local ped = PlayerPedId() 79 | if not IsPedInAnyVehicle(ped, false) then return end 80 | 81 | local _harness = false 82 | if items then 83 | for _, v in pairs(items) do 84 | if v.name == 'harness' then 85 | _harness = true 86 | end 87 | end 88 | end 89 | 90 | harness = _harness 91 | end 92 | 93 | RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() 94 | Wait(2000) 95 | local hudSettings = GetResourceKvpString('hudSettings') 96 | if hudSettings then loadSettings(json.decode(hudSettings)) end 97 | PlayerData = QBCore.Functions.GetPlayerData() 98 | Wait(3000) 99 | SetEntityHealth(PlayerPedId(), 200) 100 | end) 101 | 102 | RegisterNetEvent('QBCore:Client:OnPlayerUnload', function() 103 | PlayerData = {} 104 | end) 105 | 106 | RegisterNetEvent('QBCore:Player:SetPlayerData', function(val) 107 | PlayerData = val 108 | end) 109 | 110 | AddEventHandler('onResourceStart', function(resourceName) 111 | if GetCurrentResourceName() ~= resourceName then return end 112 | Wait(2000) 113 | local hudSettings = GetResourceKvpString('hudSettings') 114 | if hudSettings then loadSettings(json.decode(hudSettings)) end 115 | end) 116 | 117 | AddEventHandler('pma-voice:radioActive', function(data) 118 | radioActive = data 119 | end) 120 | 121 | -- Callbacks & Events 122 | RegisterCommand('menu', function() 123 | Wait(50) 124 | if showMenu then return end 125 | TriggerEvent('hud:client:playOpenMenuSounds') 126 | SetNuiFocus(true, true) 127 | SendNUIMessage({ action = 'open' }) 128 | showMenu = true 129 | end) 130 | 131 | RegisterNUICallback('closeMenu', function(_, cb) 132 | Wait(50) 133 | TriggerEvent('hud:client:playCloseMenuSounds') 134 | showMenu = false 135 | SetNuiFocus(false, false) 136 | cb('ok') 137 | end) 138 | 139 | RegisterKeyMapping('menu', 'Open Menu', 'keyboard', config.OpenMenu) 140 | 141 | -- Reset hud 142 | local function restartHud() 143 | TriggerEvent('hud:client:playResetHudSounds') 144 | QBCore.Functions.Notify(Lang:t('notify.hud_restart'), 'error') 145 | if IsPedInAnyVehicle(PlayerPedId()) then 146 | Wait(2600) 147 | SendNUIMessage({ action = 'car', show = false }) 148 | SendNUIMessage({ action = 'car', show = true }) 149 | end 150 | Wait(2600) 151 | SendNUIMessage({ action = 'hudtick', show = false }) 152 | SendNUIMessage({ action = 'hudtick', show = true }) 153 | Wait(2600) 154 | QBCore.Functions.Notify(Lang:t('notify.hud_start'), 'success') 155 | end 156 | 157 | RegisterNUICallback('restartHud', function(_, cb) 158 | Wait(50) 159 | restartHud() 160 | cb('ok') 161 | end) 162 | 163 | RegisterCommand('resethud', function() 164 | Wait(50) 165 | restartHud() 166 | end) 167 | 168 | RegisterNUICallback('resetStorage', function(_, cb) 169 | Wait(50) 170 | TriggerEvent('hud:client:resetStorage') 171 | cb('ok') 172 | end) 173 | 174 | RegisterNetEvent('hud:client:resetStorage', function() 175 | Wait(50) 176 | if Menu.isResetSoundsChecked then 177 | TriggerServerEvent('InteractSound_SV:PlayOnSource', 'airwrench', 0.1) 178 | end 179 | QBCore.Functions.TriggerCallback('hud:server:getMenu', function(menu) 180 | loadSettings(menu); SetResourceKvp('hudSettings', json.encode(menu)) 181 | end) 182 | end) 183 | 184 | -- Notifications 185 | RegisterNUICallback('openMenuSounds', function(_, cb) 186 | Wait(50) 187 | Menu.isOpenMenuSoundsChecked = not Menu.isOpenMenuSoundsChecked 188 | TriggerEvent('hud:client:playHudChecklistSound') 189 | saveSettings() 190 | cb('ok') 191 | end) 192 | 193 | RegisterNetEvent('hud:client:playOpenMenuSounds', function() 194 | Wait(50) 195 | if not Menu.isOpenMenuSoundsChecked then return end 196 | TriggerServerEvent('InteractSound_SV:PlayOnSource', 'monkeyopening', 0.5) 197 | end) 198 | 199 | RegisterNetEvent('hud:client:playCloseMenuSounds', function() 200 | Wait(50) 201 | if not Menu.isOpenMenuSoundsChecked then return end 202 | TriggerServerEvent('InteractSound_SV:PlayOnSource', 'catclosing', 0.05) 203 | end) 204 | 205 | RegisterNUICallback('resetHudSounds', function(_, cb) 206 | Wait(50) 207 | Menu.isResetSoundsChecked = not Menu.isResetSoundsChecked 208 | TriggerEvent('hud:client:playHudChecklistSound') 209 | saveSettings() 210 | cb('ok') 211 | end) 212 | 213 | RegisterNetEvent('hud:client:playResetHudSounds', function() 214 | Wait(50) 215 | if not Menu.isResetSoundsChecked then return end 216 | TriggerServerEvent('InteractSound_SV:PlayOnSource', 'airwrench', 0.1) 217 | end) 218 | 219 | RegisterNUICallback('checklistSounds', function(_, cb) 220 | Wait(50) 221 | TriggerEvent('hud:client:checklistSounds') 222 | cb('ok') 223 | end) 224 | 225 | RegisterNetEvent('hud:client:checklistSounds', function() 226 | Wait(50) 227 | Menu.isListSoundsChecked = not Menu.isListSoundsChecked 228 | TriggerEvent('hud:client:playHudChecklistSound') 229 | saveSettings() 230 | end) 231 | 232 | RegisterNetEvent('hud:client:playHudChecklistSound', function() 233 | Wait(50) 234 | if not Menu.isListSoundsChecked then return end 235 | TriggerServerEvent('InteractSound_SV:PlayOnSource', 'shiftyclick', 0.5) 236 | end) 237 | 238 | RegisterNUICallback('showOutMap', function(_, cb) 239 | Wait(50) 240 | Menu.isOutMapChecked = not Menu.isOutMapChecked 241 | TriggerEvent('hud:client:playHudChecklistSound') 242 | saveSettings() 243 | cb('ok') 244 | end) 245 | 246 | RegisterNUICallback('showOutCompass', function(_, cb) 247 | Wait(50) 248 | Menu.isOutCompassChecked = not Menu.isOutCompassChecked 249 | TriggerEvent('hud:client:playHudChecklistSound') 250 | saveSettings() 251 | cb('ok') 252 | end) 253 | 254 | RegisterNUICallback('showFollowCompass', function(_, cb) 255 | Wait(50) 256 | Menu.isCompassFollowChecked = not Menu.isCompassFollowChecked 257 | TriggerEvent('hud:client:playHudChecklistSound') 258 | saveSettings() 259 | cb('ok') 260 | end) 261 | 262 | RegisterNUICallback('showMapNotif', function(_, cb) 263 | Wait(50) 264 | Menu.isMapNotifChecked = not Menu.isMapNotifChecked 265 | TriggerEvent('hud:client:playHudChecklistSound') 266 | saveSettings() 267 | cb('ok') 268 | end) 269 | 270 | RegisterNUICallback('showFuelAlert', function(_, cb) 271 | Wait(50) 272 | Menu.isLowFuelChecked = not Menu.isLowFuelChecked 273 | TriggerEvent('hud:client:playHudChecklistSound') 274 | saveSettings() 275 | cb('ok') 276 | end) 277 | 278 | RegisterNUICallback('showCinematicNotif', function(_, cb) 279 | Wait(50) 280 | Menu.isCinematicNotifChecked = not Menu.isCinematicNotifChecked 281 | TriggerEvent('hud:client:playHudChecklistSound') 282 | saveSettings() 283 | cb('ok') 284 | end) 285 | 286 | -- Status 287 | RegisterNUICallback('dynamicHealth', function(_, cb) 288 | Wait(50) 289 | TriggerEvent('hud:client:ToggleHealth') 290 | cb('ok') 291 | end) 292 | 293 | RegisterNetEvent('hud:client:ToggleHealth', function() 294 | Wait(50) 295 | Menu.isDynamicHealthChecked = not Menu.isDynamicHealthChecked 296 | TriggerEvent('hud:client:playHudChecklistSound') 297 | saveSettings() 298 | end) 299 | 300 | RegisterNUICallback('dynamicArmor', function(_, cb) 301 | Wait(50) 302 | Menu.isDynamicArmorChecked = not Menu.isDynamicArmorChecked 303 | TriggerEvent('hud:client:playHudChecklistSound') 304 | saveSettings() 305 | cb('ok') 306 | end) 307 | 308 | RegisterNUICallback('dynamicHunger', function(_, cb) 309 | Wait(50) 310 | Menu.isDynamicHungerChecked = not Menu.isDynamicHungerChecked 311 | TriggerEvent('hud:client:playHudChecklistSound') 312 | saveSettings() 313 | cb('ok') 314 | end) 315 | 316 | RegisterNUICallback('dynamicThirst', function(_, cb) 317 | Wait(50) 318 | Menu.isDynamicThirstChecked = not Menu.isDynamicThirstChecked 319 | TriggerEvent('hud:client:playHudChecklistSound') 320 | saveSettings() 321 | cb('ok') 322 | end) 323 | 324 | RegisterNUICallback('dynamicStress', function(_, cb) 325 | Wait(50) 326 | Menu.isDynamicStressChecked = not Menu.isDynamicStressChecked 327 | TriggerEvent('hud:client:playHudChecklistSound') 328 | saveSettings() 329 | cb('ok') 330 | end) 331 | 332 | RegisterNUICallback('dynamicOxygen', function(_, cb) 333 | Wait(50) 334 | Menu.isDynamicOxygenChecked = not Menu.isDynamicOxygenChecked 335 | TriggerEvent('hud:client:playHudChecklistSound') 336 | saveSettings() 337 | cb('ok') 338 | end) 339 | 340 | -- Vehicle 341 | RegisterNUICallback('changeFPS', function(_, cb) 342 | Wait(50) 343 | Menu.isChangeFPSChecked = not Menu.isChangeFPSChecked 344 | TriggerEvent('hud:client:playHudChecklistSound') 345 | saveSettings() 346 | cb('ok') 347 | end) 348 | 349 | RegisterNUICallback('HideMap', function(_, cb) 350 | Wait(50) 351 | Menu.isHideMapChecked = not Menu.isHideMapChecked 352 | DisplayRadar(not Menu.isHideMapChecked) 353 | TriggerEvent('hud:client:playHudChecklistSound') 354 | saveSettings() 355 | cb('ok') 356 | end) 357 | 358 | RegisterNetEvent('hud:client:LoadMap', function() 359 | Wait(50) 360 | -- Credit to Dalrae for the solve. 361 | local defaultAspectRatio = 1920 / 1080 -- Don't change this. 362 | local resolutionX, resolutionY = GetActiveScreenResolution() 363 | local aspectRatio = resolutionX / resolutionY 364 | local minimapOffset = 0 365 | if aspectRatio > defaultAspectRatio then 366 | minimapOffset = ((defaultAspectRatio - aspectRatio) / 3.6) - 0.008 367 | end 368 | if Menu.isToggleMapShapeChecked == 'square' then 369 | RequestStreamedTextureDict('squaremap', false) 370 | if not HasStreamedTextureDictLoaded('squaremap') then 371 | Wait(150) 372 | end 373 | if Menu.isMapNotifChecked then 374 | QBCore.Functions.Notify(Lang:t('notify.load_square_map')) 375 | end 376 | SetMinimapClipType(0) 377 | AddReplaceTexture('platform:/textures/graphics', 'radarmasksm', 'squaremap', 'radarmasksm') 378 | AddReplaceTexture('platform:/textures/graphics', 'radarmask1g', 'squaremap', 'radarmasksm') 379 | -- 0.0 = nav symbol and icons left 380 | -- 0.1638 = nav symbol and icons stretched 381 | -- 0.216 = nav symbol and icons raised up 382 | SetMinimapComponentPosition('minimap', 'L', 'B', 0.0 + minimapOffset, -0.047, 0.1638, 0.183) 383 | 384 | -- icons within map 385 | SetMinimapComponentPosition('minimap_mask', 'L', 'B', 0.0 + minimapOffset, 0.0, 0.128, 0.20) 386 | 387 | -- -0.01 = map pulled left 388 | -- 0.025 = map raised up 389 | -- 0.262 = map stretched 390 | -- 0.315 = map shorten 391 | SetMinimapComponentPosition('minimap_blur', 'L', 'B', -0.01 + minimapOffset, 0.025, 0.262, 0.300) 392 | SetBlipAlpha(GetNorthRadarBlip(), 0) 393 | SetBigmapActive(true, false) 394 | SetMinimapClipType(0) 395 | Wait(50) 396 | SetBigmapActive(false, false) 397 | if Menu.isToggleMapBordersChecked then 398 | showCircleB = false 399 | showSquareB = true 400 | end 401 | Wait(1200) 402 | if Menu.isMapNotifChecked then 403 | QBCore.Functions.Notify(Lang:t('notify.loaded_square_map')) 404 | end 405 | elseif Menu.isToggleMapShapeChecked == 'circle' then 406 | RequestStreamedTextureDict('circlemap', false) 407 | if not HasStreamedTextureDictLoaded('circlemap') then 408 | Wait(150) 409 | end 410 | if Menu.isMapNotifChecked then 411 | QBCore.Functions.Notify(Lang:t('notify.load_circle_map')) 412 | end 413 | SetMinimapClipType(1) 414 | AddReplaceTexture('platform:/textures/graphics', 'radarmasksm', 'circlemap', 'radarmasksm') 415 | AddReplaceTexture('platform:/textures/graphics', 'radarmask1g', 'circlemap', 'radarmasksm') 416 | -- -0.0100 = nav symbol and icons left 417 | -- 0.180 = nav symbol and icons stretched 418 | -- 0.258 = nav symbol and icons raised up 419 | SetMinimapComponentPosition('minimap', 'L', 'B', -0.0100 + minimapOffset, -0.030, 0.180, 0.258) 420 | 421 | -- icons within map 422 | SetMinimapComponentPosition('minimap_mask', 'L', 'B', 0.200 + minimapOffset, 0.0, 0.065, 0.20) 423 | 424 | -- -0.00 = map pulled left 425 | -- 0.015 = map raised up 426 | -- 0.252 = map stretched 427 | -- 0.338 = map shorten 428 | SetMinimapComponentPosition('minimap_blur', 'L', 'B', -0.00 + minimapOffset, 0.015, 0.252, 0.338) 429 | SetBlipAlpha(GetNorthRadarBlip(), 0) 430 | SetMinimapClipType(1) 431 | SetBigmapActive(true, false) 432 | Wait(50) 433 | SetBigmapActive(false, false) 434 | if Menu.isToggleMapBordersChecked then 435 | showSquareB = false 436 | showCircleB = true 437 | end 438 | Wait(1200) 439 | if Menu.isMapNotifChecked then 440 | QBCore.Functions.Notify(Lang:t('notify.loaded_circle_map')) 441 | end 442 | end 443 | end) 444 | 445 | RegisterNUICallback('ToggleMapShape', function(_, cb) 446 | Wait(50) 447 | if not Menu.isHideMapChecked then 448 | Menu.isToggleMapShapeChecked = Menu.isToggleMapShapeChecked == 'circle' and 'square' or 'circle' 449 | Wait(50) 450 | TriggerEvent('hud:client:LoadMap') 451 | end 452 | TriggerEvent('hud:client:playHudChecklistSound') 453 | saveSettings() 454 | cb('ok') 455 | end) 456 | 457 | RegisterNUICallback('ToggleMapBorders', function(_, cb) 458 | Wait(50) 459 | Menu.isToggleMapBordersChecked = not Menu.isToggleMapBordersChecked 460 | if Menu.isToggleMapBordersChecked then 461 | if Menu.isToggleMapShapeChecked == 'square' then 462 | showSquareB = true 463 | else 464 | showCircleB = true 465 | end 466 | else 467 | showSquareB = false 468 | showCircleB = false 469 | end 470 | TriggerEvent('hud:client:playHudChecklistSound') 471 | saveSettings() 472 | cb('ok') 473 | end) 474 | 475 | RegisterNUICallback('dynamicEngine', function(_, cb) 476 | Wait(50) 477 | Menu.isDynamicEngineChecked = not Menu.isDynamicEngineChecked 478 | TriggerEvent('hud:client:playHudChecklistSound') 479 | saveSettings() 480 | cb('ok') 481 | end) 482 | 483 | RegisterNUICallback('dynamicNitro', function(_, cb) 484 | Wait(50) 485 | Menu.isDynamicNitroChecked = not Menu.isDynamicNitroChecked 486 | TriggerEvent('hud:client:playHudChecklistSound') 487 | saveSettings() 488 | cb('ok') 489 | end) 490 | 491 | -- Compass 492 | RegisterNUICallback('showCompassBase', function(_, cb) 493 | Wait(50) 494 | Menu.isCompassShowChecked = not Menu.isCompassShowChecked 495 | TriggerEvent('hud:client:playHudChecklistSound') 496 | saveSettings() 497 | cb('ok') 498 | end) 499 | 500 | RegisterNUICallback('showStreetsNames', function(_, cb) 501 | Wait(50) 502 | Menu.isShowStreetsChecked = not Menu.isShowStreetsChecked 503 | TriggerEvent('hud:client:playHudChecklistSound') 504 | saveSettings() 505 | cb('ok') 506 | end) 507 | 508 | RegisterNUICallback('showPointerIndex', function(_, cb) 509 | Wait(50) 510 | Menu.isPointerShowChecked = not Menu.isPointerShowChecked 511 | TriggerEvent('hud:client:playHudChecklistSound') 512 | saveSettings() 513 | cb('ok') 514 | end) 515 | 516 | RegisterNUICallback('showDegreesNum', function(_, cb) 517 | Wait(50) 518 | Menu.isDegreesShowChecked = not Menu.isDegreesShowChecked 519 | TriggerEvent('hud:client:playHudChecklistSound') 520 | saveSettings() 521 | cb('ok') 522 | end) 523 | 524 | RegisterNUICallback('changeCompassFPS', function(_, cb) 525 | Wait(50) 526 | Menu.isChangeCompassFPSChecked = not Menu.isChangeCompassFPSChecked 527 | TriggerEvent('hud:client:playHudChecklistSound') 528 | saveSettings() 529 | cb('ok') 530 | end) 531 | 532 | RegisterNUICallback('cinematicMode', function(_, cb) 533 | Wait(50) 534 | if Menu.isCinematicModeChecked then 535 | CinematicShow(false) 536 | Menu.isCinematicModeChecked = false 537 | if Menu.isCinematicNotifChecked then 538 | QBCore.Functions.Notify(Lang:t('notify.cinematic_off'), 'error') 539 | end 540 | DisplayRadar(1) 541 | else 542 | CinematicShow(true) 543 | Menu.isCinematicModeChecked = true 544 | if Menu.isCinematicNotifChecked then 545 | QBCore.Functions.Notify(Lang:t('notify.cinematic_on')) 546 | end 547 | end 548 | TriggerEvent('hud:client:playHudChecklistSound') 549 | saveSettings() 550 | cb('ok') 551 | end) 552 | 553 | RegisterNetEvent('hud:client:ToggleAirHud', function() 554 | showAltitude = not showAltitude 555 | end) 556 | 557 | RegisterNetEvent('hud:client:UpdateNeeds', function(newHunger, newThirst) -- Triggered in qb-core 558 | hunger = newHunger 559 | thirst = newThirst 560 | end) 561 | 562 | RegisterNetEvent('hud:client:UpdateStress', function(newStress) -- Add this event with adding stress elsewhere 563 | stress = newStress 564 | end) 565 | 566 | RegisterNetEvent('hud:client:ToggleShowSeatbelt', function() 567 | showSeatbelt = not showSeatbelt 568 | end) 569 | 570 | RegisterNetEvent('seatbelt:client:ToggleSeatbelt', function() -- Triggered in smallresources 571 | seatbeltOn = not seatbeltOn 572 | end) 573 | 574 | RegisterNetEvent('seatbelt:client:ToggleCruise', function() -- Triggered in smallresources 575 | cruiseOn = not cruiseOn 576 | end) 577 | 578 | RegisterNetEvent('hud:client:UpdateNitrous', function(nitroLevel, bool) 579 | nos = nitroLevel 580 | nitroActive = bool 581 | end) 582 | 583 | RegisterNetEvent('hud:client:UpdateHarness', function(harnessHp) 584 | hp = harnessHp 585 | end) 586 | 587 | RegisterNetEvent('qb-admin:client:ToggleDevmode', function() 588 | dev = not dev 589 | end) 590 | 591 | local prevPlayerStats = { nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil } 592 | 593 | local function updatePlayerHud(data) 594 | local shouldUpdate = false 595 | for k, v in pairs(data) do 596 | if prevPlayerStats[k] ~= v then 597 | shouldUpdate = true 598 | break 599 | end 600 | end 601 | prevPlayerStats = data 602 | if shouldUpdate then 603 | SendNUIMessage({ 604 | action = 'hudtick', 605 | show = data[1], 606 | dynamicHealth = data[2], 607 | dynamicArmor = data[3], 608 | dynamicHunger = data[4], 609 | dynamicThirst = data[5], 610 | dynamicStress = data[6], 611 | dynamicOxygen = data[7], 612 | dynamicEngine = data[8], 613 | dynamicNitro = data[9], 614 | health = data[10], 615 | playerDead = data[11], 616 | armor = data[12], 617 | thirst = data[13], 618 | hunger = data[14], 619 | stress = data[15], 620 | voice = data[16], 621 | radio = data[17], 622 | talking = data[18], 623 | armed = data[19], 624 | oxygen = data[20], 625 | parachute = data[21], 626 | nos = data[22], 627 | cruise = data[23], 628 | nitroActive = data[24], 629 | harness = data[25], 630 | hp = data[26], 631 | speed = data[27], 632 | engine = data[28], 633 | cinematic = data[29], 634 | dev = data[30], 635 | radioActive = data[31], 636 | }) 637 | end 638 | end 639 | 640 | local prevVehicleStats = { nil, nil, nil, nil, nil, nil, nil, nil, nil, nil } 641 | 642 | local function updateVehicleHud(data) 643 | local shouldUpdate = false 644 | for k, v in pairs(data) do 645 | if prevVehicleStats[k] ~= v then 646 | shouldUpdate = true 647 | break 648 | end 649 | end 650 | prevVehicleStats = data 651 | if shouldUpdate then 652 | SendNUIMessage({ 653 | action = 'car', 654 | show = data[1], 655 | isPaused = data[2], 656 | seatbelt = data[3], 657 | speed = data[4], 658 | fuel = data[5], 659 | altitude = data[6], 660 | showAltitude = data[7], 661 | showSeatbelt = data[8], 662 | showSquareB = data[9], 663 | showCircleB = data[10], 664 | }) 665 | end 666 | end 667 | 668 | local lastFuelUpdate = 0 669 | local lastFuelCheck = {} 670 | 671 | local function getFuelLevel(vehicle) 672 | local updateTick = GetGameTimer() 673 | if (updateTick - lastFuelUpdate) > 2000 then 674 | lastFuelUpdate = updateTick 675 | lastFuelCheck = math.floor(exports['LegacyFuel']:GetFuel(vehicle)) 676 | end 677 | return lastFuelCheck 678 | end 679 | 680 | -- HUD Update loop 681 | 682 | CreateThread(function() 683 | local wasInVehicle = false 684 | while true do 685 | if Menu.isChangeFPSChecked then 686 | Wait(500) 687 | else 688 | Wait(50) 689 | end 690 | if LocalPlayer.state.isLoggedIn then 691 | local show = true 692 | local player = PlayerPedId() 693 | local playerId = PlayerId() 694 | local weapon = GetSelectedPedWeapon(player) 695 | -- Player hud 696 | if not config.WhitelistedWeaponArmed[weapon] then 697 | if weapon ~= `WEAPON_UNARMED` then 698 | armed = true 699 | else 700 | armed = false 701 | end 702 | end 703 | playerDead = IsEntityDead(player) or PlayerData.metadata['inlaststand'] or PlayerData.metadata['isdead'] or false 704 | parachute = GetPedParachuteState(player) 705 | -- Stamina 706 | if not IsEntityInWater(player) then 707 | oxygen = 100 - GetPlayerSprintStaminaRemaining(playerId) 708 | end 709 | -- Oxygen 710 | if IsEntityInWater(player) then 711 | oxygen = GetPlayerUnderwaterTimeRemaining(playerId) * 10 712 | end 713 | -- Player hud 714 | local talking = NetworkIsPlayerTalking(playerId) 715 | local voice = 0 716 | if LocalPlayer.state['proximity'] then 717 | voice = LocalPlayer.state['proximity'].distance 718 | end 719 | if IsPauseMenuActive() then 720 | show = false 721 | end 722 | local vehicle = GetVehiclePedIsIn(player) 723 | if not (IsPedInAnyVehicle(player) and not IsThisModelABicycle(vehicle)) then 724 | updatePlayerHud({ 725 | show, 726 | Menu.isDynamicHealthChecked, 727 | Menu.isDynamicArmorChecked, 728 | Menu.isDynamicHungerChecked, 729 | Menu.isDynamicThirstChecked, 730 | Menu.isDynamicStressChecked, 731 | Menu.isDynamicOxygenChecked, 732 | Menu.isDynamicEngineChecked, 733 | Menu.isDynamicNitroChecked, 734 | GetEntityHealth(player) - 100, 735 | playerDead, 736 | GetPedArmour(player), 737 | thirst, 738 | hunger, 739 | stress, 740 | voice, 741 | LocalPlayer.state['radioChannel'], 742 | talking, 743 | armed, 744 | oxygen, 745 | parachute, 746 | -1, 747 | cruiseOn, 748 | nitroActive, 749 | harness, 750 | hp, 751 | math.ceil(GetEntitySpeed(vehicle) * speedMultiplier), 752 | -1, 753 | Menu.isCinematicModeChecked, 754 | dev, 755 | radioActive, 756 | }) 757 | end 758 | -- Vehicle hud 759 | if IsPedInAnyHeli(player) or IsPedInAnyPlane(player) then 760 | showAltitude = true 761 | showSeatbelt = false 762 | end 763 | if IsPedInAnyVehicle(player) and not IsThisModelABicycle(vehicle) then 764 | if not wasInVehicle then 765 | DisplayRadar(true) 766 | end 767 | wasInVehicle = true 768 | local engineHealth = GetVehicleEngineHealth(vehicle) 769 | if engineHealth ~= engineHealth then -- This checks for NaN, as any NaN value is not equal to itself 770 | engineHealth = 0 771 | end 772 | updatePlayerHud({ 773 | show, 774 | Menu.isDynamicHealthChecked, 775 | Menu.isDynamicArmorChecked, 776 | Menu.isDynamicHungerChecked, 777 | Menu.isDynamicThirstChecked, 778 | Menu.isDynamicStressChecked, 779 | Menu.isDynamicOxygenChecked, 780 | Menu.isDynamicEngineChecked, 781 | Menu.isDynamicNitroChecked, 782 | GetEntityHealth(player) - 100, 783 | playerDead, 784 | GetPedArmour(player), 785 | thirst, 786 | hunger, 787 | stress, 788 | voice, 789 | LocalPlayer.state['radioChannel'], 790 | talking, 791 | armed, 792 | oxygen, 793 | GetPedParachuteState(player), 794 | nos, 795 | cruiseOn, 796 | nitroActive, 797 | harness, 798 | hp, 799 | math.ceil(GetEntitySpeed(vehicle) * speedMultiplier), 800 | (engineHealth / 10), 801 | Menu.isCinematicModeChecked, 802 | dev, 803 | radioActive, 804 | }) 805 | updateVehicleHud({ 806 | show, 807 | IsPauseMenuActive(), 808 | seatbeltOn, 809 | math.ceil(GetEntitySpeed(vehicle) * speedMultiplier), 810 | getFuelLevel(vehicle), 811 | math.ceil(GetEntityCoords(player).z * 0.5), 812 | showAltitude, 813 | showSeatbelt, 814 | showSquareB, 815 | showCircleB, 816 | }) 817 | showAltitude = false 818 | showSeatbelt = true 819 | else 820 | if wasInVehicle then 821 | wasInVehicle = false 822 | SendNUIMessage({ 823 | action = 'car', 824 | show = false, 825 | seatbelt = false, 826 | cruise = false, 827 | }) 828 | seatbeltOn = false 829 | cruiseOn = false 830 | harness = false 831 | end 832 | DisplayRadar(Menu.isOutMapChecked) 833 | end 834 | else 835 | SendNUIMessage({ 836 | action = 'hudtick', 837 | show = false 838 | }) 839 | end 840 | end 841 | end) 842 | 843 | -- Low fuel 844 | CreateThread(function() 845 | while true do 846 | if LocalPlayer.state.isLoggedIn then 847 | local ped = PlayerPedId() 848 | if IsPedInAnyVehicle(ped, false) and not IsThisModelABicycle(GetEntityModel(GetVehiclePedIsIn(ped, false))) then 849 | if exports['LegacyFuel']:GetFuel(GetVehiclePedIsIn(ped, false)) <= 20 then -- At 20% Fuel Left 850 | if Menu.isLowFuelChecked then 851 | TriggerServerEvent('InteractSound_SV:PlayOnSource', 'pager', 0.10) 852 | QBCore.Functions.Notify(Lang:t('notify.low_fuel'), 'error') 853 | Wait(60000) -- repeats every 1 min until empty 854 | end 855 | end 856 | end 857 | end 858 | Wait(10000) 859 | end 860 | end) 861 | 862 | -- Money HUD 863 | 864 | local Round = math.floor 865 | 866 | RegisterNetEvent('hud:client:ShowAccounts', function(type, amount) 867 | if type == 'cash' then 868 | SendNUIMessage({ 869 | action = 'show', 870 | type = 'cash', 871 | cash = Round(amount) 872 | }) 873 | else 874 | SendNUIMessage({ 875 | action = 'show', 876 | type = 'bank', 877 | bank = Round(amount) 878 | }) 879 | end 880 | end) 881 | 882 | RegisterNetEvent('hud:client:OnMoneyChange', function(type, amount, isMinus) 883 | cashAmount = PlayerData.money['cash'] 884 | bankAmount = PlayerData.money['bank'] 885 | SendNUIMessage({ 886 | action = 'updatemoney', 887 | cash = Round(cashAmount), 888 | bank = Round(bankAmount), 889 | amount = Round(amount), 890 | minus = isMinus, 891 | type = type 892 | }) 893 | end) 894 | 895 | -- Harness Check 896 | 897 | CreateThread(function() 898 | while true do 899 | Wait(1000) 900 | 901 | local ped = PlayerPedId() 902 | if IsPedInAnyVehicle(ped, false) then 903 | hasHarness(PlayerData.items) 904 | end 905 | end 906 | end) 907 | 908 | -- Stress Gain 909 | 910 | if not config.DisableStress then 911 | CreateThread(function() -- Speeding 912 | while true do 913 | if LocalPlayer.state.isLoggedIn then 914 | local ped = PlayerPedId() 915 | if IsPedInAnyVehicle(ped, false) then 916 | local veh = GetVehiclePedIsIn(ped, false) 917 | local vehClass = GetVehicleClass(veh) 918 | local speed = GetEntitySpeed(veh) * speedMultiplier 919 | local vehHash = GetEntityModel(veh) 920 | if config.VehClassStress[tostring(vehClass)] and not config.WhitelistedVehicles[vehHash] then 921 | local stressSpeed 922 | if vehClass == 8 then -- Motorcycle exception for seatbelt 923 | stressSpeed = config.MinimumSpeed 924 | else 925 | stressSpeed = seatbeltOn and config.MinimumSpeed or config.MinimumSpeedUnbuckled 926 | end 927 | if speed >= stressSpeed then 928 | TriggerServerEvent('hud:server:GainStress', math.random(1, 3)) 929 | end 930 | end 931 | end 932 | end 933 | Wait(10000) 934 | end 935 | end) 936 | 937 | CreateThread(function() -- Shooting 938 | while true do 939 | if LocalPlayer.state.isLoggedIn then 940 | local ped = PlayerPedId() 941 | local weapon = GetSelectedPedWeapon(ped) 942 | if weapon ~= `WEAPON_UNARMED` then 943 | if IsPedShooting(ped) and not config.WhitelistedWeaponStress[weapon] then 944 | if math.random() < config.StressChance then 945 | TriggerServerEvent('hud:server:GainStress', math.random(1, 3)) 946 | end 947 | end 948 | else 949 | Wait(1000) 950 | end 951 | end 952 | Wait(0) 953 | end 954 | end) 955 | end 956 | 957 | -- Stress Screen Effects 958 | 959 | local function GetBlurIntensity(stresslevel) 960 | for _, v in pairs(config.Intensity['blur']) do 961 | if stresslevel >= v.min and stresslevel <= v.max then 962 | return v.intensity 963 | end 964 | end 965 | return 1500 966 | end 967 | 968 | local function GetEffectInterval(stresslevel) 969 | for _, v in pairs(config.EffectInterval) do 970 | if stresslevel >= v.min and stresslevel <= v.max then 971 | return v.timeout 972 | end 973 | end 974 | return 60000 975 | end 976 | 977 | CreateThread(function() 978 | while true do 979 | local ped = PlayerPedId() 980 | local effectInterval = GetEffectInterval(stress) 981 | if stress >= 100 then 982 | local BlurIntensity = GetBlurIntensity(stress) 983 | local FallRepeat = math.random(2, 4) 984 | local RagdollTimeout = FallRepeat * 1750 985 | TriggerScreenblurFadeIn(1000.0) 986 | Wait(BlurIntensity) 987 | TriggerScreenblurFadeOut(1000.0) 988 | 989 | if not IsPedRagdoll(ped) and IsPedOnFoot(ped) and not IsPedSwimming(ped) then 990 | SetPedToRagdollWithFall(ped, RagdollTimeout, RagdollTimeout, 1, GetEntityForwardVector(ped), 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) 991 | end 992 | 993 | Wait(1000) 994 | for _ = 1, FallRepeat, 1 do 995 | Wait(750) 996 | DoScreenFadeOut(200) 997 | Wait(1000) 998 | DoScreenFadeIn(200) 999 | TriggerScreenblurFadeIn(1000.0) 1000 | Wait(BlurIntensity) 1001 | TriggerScreenblurFadeOut(1000.0) 1002 | end 1003 | elseif stress >= config.MinimumStress then 1004 | local BlurIntensity = GetBlurIntensity(stress) 1005 | TriggerScreenblurFadeIn(1000.0) 1006 | Wait(BlurIntensity) 1007 | TriggerScreenblurFadeOut(1000.0) 1008 | end 1009 | Wait(effectInterval) 1010 | end 1011 | end) 1012 | 1013 | -- Minimap update 1014 | CreateThread(function() 1015 | while true do 1016 | SetBigmapActive(false, false) 1017 | SetRadarZoom(1000) 1018 | Wait(500) 1019 | end 1020 | end) 1021 | 1022 | local function BlackBars() 1023 | DrawRect(0.0, 0.0, 2.0, w, 0, 0, 0, 255) 1024 | DrawRect(0.0, 1.0, 2.0, w, 0, 0, 0, 255) 1025 | end 1026 | 1027 | CreateThread(function() 1028 | local minimap = RequestScaleformMovie('minimap') 1029 | if not HasScaleformMovieLoaded(minimap) then 1030 | RequestScaleformMovie(minimap) 1031 | while not HasScaleformMovieLoaded(minimap) do 1032 | Wait(1) 1033 | end 1034 | end 1035 | while true do 1036 | if w > 0 then 1037 | BlackBars() 1038 | DisplayRadar(0) 1039 | SendNUIMessage({ 1040 | action = 'hudtick', 1041 | show = false, 1042 | }) 1043 | SendNUIMessage({ 1044 | action = 'car', 1045 | show = false, 1046 | }) 1047 | end 1048 | Wait(0) 1049 | end 1050 | end) 1051 | 1052 | local prevBaseplateStats = { nil, nil, nil, nil, nil, nil, nil } 1053 | 1054 | local function updateBaseplateHud(data) 1055 | local shouldUpdate = false 1056 | for k, v in pairs(data) do 1057 | if prevBaseplateStats[k] ~= v then 1058 | shouldUpdate = true 1059 | break 1060 | end 1061 | end 1062 | prevBaseplateStats = data 1063 | if shouldUpdate then 1064 | SendNUIMessage({ 1065 | action = 'baseplate', 1066 | show = data[1], 1067 | street1 = data[2], 1068 | street2 = data[3], 1069 | showCompass = data[4], 1070 | showStreets = data[5], 1071 | showPointer = data[6], 1072 | showDegrees = data[7], 1073 | }) 1074 | end 1075 | end 1076 | 1077 | local lastCrossroadUpdate = 0 1078 | local lastCrossroadCheck = {} 1079 | 1080 | local function getCrossroads(player) 1081 | local updateTick = GetGameTimer() 1082 | if updateTick - lastCrossroadUpdate > 1500 then 1083 | local pos = GetEntityCoords(player) 1084 | local street1, street2 = GetStreetNameAtCoord(pos.x, pos.y, pos.z) 1085 | lastCrossroadUpdate = updateTick 1086 | lastCrossroadCheck = { GetStreetNameFromHashKey(street1), GetStreetNameFromHashKey(street2) } 1087 | end 1088 | return lastCrossroadCheck 1089 | end 1090 | 1091 | -- Compass Update loop 1092 | 1093 | CreateThread(function() 1094 | local lastHeading = 1 1095 | local heading 1096 | while true do 1097 | if Menu.isChangeCompassFPSChecked then 1098 | Wait(50) 1099 | else 1100 | Wait(0) 1101 | end 1102 | local show = true 1103 | local player = PlayerPedId() 1104 | local camRot = GetGameplayCamRot(0) 1105 | if Menu.isCompassFollowChecked then 1106 | heading = tostring(QBCore.Shared.Round(360.0 - ((camRot.z + 360.0) % 360.0))) 1107 | else 1108 | heading = tostring(QBCore.Shared.Round(360.0 - GetEntityHeading(player))) 1109 | end 1110 | if heading == '360' then heading = '0' end 1111 | if heading ~= lastHeading then 1112 | if IsPedInAnyVehicle(player) then 1113 | local crossroads = getCrossroads(player) 1114 | SendNUIMessage({ 1115 | action = 'update', 1116 | value = heading 1117 | }) 1118 | updateBaseplateHud({ 1119 | show, 1120 | crossroads[1], 1121 | crossroads[2], 1122 | Menu.isCompassShowChecked, 1123 | Menu.isShowStreetsChecked, 1124 | Menu.isPointerShowChecked, 1125 | Menu.isDegreesShowChecked, 1126 | }) 1127 | else 1128 | if Menu.isOutCompassChecked then 1129 | SendNUIMessage({ 1130 | action = 'update', 1131 | value = heading 1132 | }) 1133 | SendNUIMessage({ 1134 | action = 'baseplate', 1135 | show = true, 1136 | showCompass = true, 1137 | }) 1138 | else 1139 | SendNUIMessage({ 1140 | action = 'baseplate', 1141 | show = false, 1142 | }) 1143 | end 1144 | end 1145 | end 1146 | lastHeading = heading 1147 | end 1148 | end) 1149 | -------------------------------------------------------------------------------- /html/app.js: -------------------------------------------------------------------------------- 1 | const { ref, onBeforeUnmount } = Vue; 2 | 3 | const app = Vue.createApp({ 4 | data: function () { 5 | return { 6 | isOutMapChecked: this.initIsOutMapChecked(), 7 | isOutCompassChecked: this.initIsOutCompassChecked(), 8 | isCompassFollowChecked: this.initIsCompassFollowChecked(), 9 | isOpenMenuSoundsChecked: this.initIsOpenMenuSoundsChecked(), 10 | isResetSoundsChecked: this.initIsResetSoundsChecked(), 11 | isListSoundsChecked: this.initIsListSoundsChecked(), 12 | isMapNotifChecked: this.initIsMapNotifChecked(), 13 | isLowFuelChecked: this.initIsLowFuelChecked(), 14 | isCinematicNotifChecked: this.initIsCinematicNotifChecked(), 15 | isDynamicHealthChecked: this.initIsDynamicHealthChecked(), 16 | isDynamicArmorChecked: this.initIsDynamicArmorChecked(), 17 | isDynamicHungerChecked: this.initIsDynamicHungerChecked(), 18 | isDynamicThirstChecked: this.initIsDynamicThirstChecked(), 19 | isDynamicStressChecked: this.initIsDynamicStressChecked(), 20 | isDynamicOxygenChecked: this.initIsDynamicOxygenChecked(), 21 | isChangeFPSChecked: this.initIsChangeFPSChecked(), 22 | isToggleMapShapeChecked: this.initIsToggleMapShapeChecked(), 23 | isHideMapChecked: this.initIsHideMapChecked(), 24 | isToggleMapBordersChecked: this.initIsToggleMapBordersChecked(), 25 | isDynamicEngineChecked: this.initIsDynamicEngineChecked(), 26 | isDynamicNitroChecked: this.initIsDynamicNitroChecked(), 27 | isChangeCompassFPSChecked: this.initIsChangeCompassFPSChecked(), 28 | isShowCompassChecked: this.initIsShowCompassChecked(), 29 | isShowStreetsChecked: this.initIsShowStreetsChecked(), 30 | isPointerShowChecked: this.initIsPointerShowChecked(), 31 | isDegreesShowChecked: this.initIsDegreesShowChecked(), 32 | isCinematicModeChecked: this.initisCinematicModeChecked(), 33 | }; 34 | }, 35 | setup() { 36 | const progress = ref([ 37 | { loading: false, percentage: 0 }, 38 | { loading: false, percentage: 0 }, 39 | { loading: false, percentage: 0 }, 40 | ]); 41 | 42 | const intervals = [null, null, null]; 43 | 44 | function startComputing(id) { 45 | progress.value[id].loading = true; 46 | progress.value[id].percentage = 0; 47 | 48 | intervals[id] = setInterval(() => { 49 | progress.value[id].percentage += Math.floor(Math.random() * 8 + 10); 50 | if (progress.value[id].percentage >= 100) { 51 | clearInterval(intervals[id]); 52 | progress.value[id].loading = false; 53 | } 54 | }, 700); 55 | } 56 | 57 | onBeforeUnmount(() => { 58 | intervals.forEach((val) => { 59 | clearInterval(val); 60 | }); 61 | }); 62 | return { 63 | framework: { 64 | plugins: ["LocalStorage", "SessionStorage"], 65 | }, 66 | tab: ref("hud"), 67 | splitterModel: ref(20), 68 | selection: ref([]), 69 | progress, 70 | startComputing, 71 | }; 72 | }, 73 | watch: { 74 | isOutMapChecked: function () { 75 | localStorage.setItem("isOutMapChecked", this.isOutMapChecked); 76 | }, 77 | isOutCompassChecked: function () { 78 | localStorage.setItem("isOutCompassChecked", this.isOutCompassChecked); 79 | }, 80 | isCompassFollowChecked: function () { 81 | localStorage.setItem("isCompassFollowChecked", this.isCompassFollowChecked); 82 | }, 83 | isOpenMenuSoundsChecked: function () { 84 | localStorage.setItem("isOpenMenuSoundsChecked", this.isOpenMenuSoundsChecked); 85 | }, 86 | isResetSoundsChecked: function () { 87 | localStorage.setItem("isResetSoundsChecked", this.isResetSoundsChecked); 88 | }, 89 | isListSoundsChecked: function () { 90 | localStorage.setItem("isListSoundsChecked", this.isListSoundsChecked); 91 | }, 92 | isMapNotifChecked: function () { 93 | localStorage.setItem("isMapNotifChecked", this.isMapNotifChecked); 94 | }, 95 | isLowFuelChecked: function () { 96 | localStorage.setItem("isLowFuelChecked", this.isLowFuelChecked); 97 | }, 98 | isCinematicNotifChecked: function () { 99 | localStorage.setItem("isCinematicNotifChecked", this.isCinematicNotifChecked); 100 | }, 101 | isDynamicHealthChecked: function () { 102 | localStorage.setItem("isDynamicHealthChecked", this.isDynamicHealthChecked); 103 | }, 104 | isDynamicArmorChecked: function () { 105 | localStorage.setItem("isDynamicArmorChecked", this.isDynamicArmorChecked); 106 | }, 107 | isDynamicHungerChecked: function () { 108 | localStorage.setItem("isDynamicHungerChecked", this.isDynamicHungerChecked); 109 | }, 110 | isDynamicThirstChecked: function () { 111 | localStorage.setItem("isDynamicThirstChecked", this.isDynamicThirstChecked); 112 | }, 113 | isDynamicStressChecked: function () { 114 | localStorage.setItem("isDynamicStressChecked", this.isDynamicStressChecked); 115 | }, 116 | isDynamicOxygenChecked: function () { 117 | localStorage.setItem("isDynamicOxygenChecked", this.isDynamicOxygenChecked); 118 | }, 119 | isChangeFPSChecked: function () { 120 | localStorage.setItem("isChangeFPSChecked", this.isChangeFPSChecked); 121 | }, 122 | isToggleMapShapeChecked: function () { 123 | localStorage.setItem("isToggleMapShapeChecked", this.isToggleMapShapeChecked); 124 | }, 125 | isHideMapChecked: function () { 126 | localStorage.setItem("isHideMapChecked", this.isHideMapChecked); 127 | }, 128 | isToggleMapBordersChecked: function () { 129 | localStorage.setItem("isToggleMapBordersChecked", this.isToggleMapBordersChecked); 130 | }, 131 | isDynamicEngineChecked: function () { 132 | localStorage.setItem("isDynamicEngineChecked", this.isDynamicEngineChecked); 133 | }, 134 | isDynamicNitroChecked: function () { 135 | localStorage.setItem("isDynamicNitroChecked", this.isDynamicNitroChecked); 136 | }, 137 | isChangeCompassFPSChecked: function () { 138 | localStorage.setItem("isChangeCompassFPSChecked", this.isChangeCompassFPSChecked); 139 | }, 140 | isShowCompassChecked: function () { 141 | localStorage.setItem("isShowCompassChecked", this.isShowCompassChecked); 142 | }, 143 | isShowStreetsChecked: function () { 144 | localStorage.setItem("isShowStreetsChecked", this.isShowStreetsChecked); 145 | }, 146 | isPointerShowChecked: function () { 147 | localStorage.setItem("isPointerShowChecked", this.isPointerShowChecked); 148 | }, 149 | isDegreesShowChecked: function () { 150 | localStorage.setItem("isDegreesShowChecked", this.isDegreesShowChecked); 151 | }, 152 | isCinematicModeChecked: function () { 153 | localStorage.setItem("isCinematicModeChecked", this.isCinematicModeChecked); 154 | }, 155 | }, 156 | methods: { 157 | initIsOutMapChecked: function () { 158 | const stored = localStorage.getItem("isOutMapChecked"); 159 | if (stored === null) { 160 | return true; 161 | } else { 162 | return stored == "true"; 163 | } 164 | }, 165 | initIsOutCompassChecked: function () { 166 | const stored = localStorage.getItem("isOutCompassChecked"); 167 | if (stored === null) { 168 | return true; 169 | } else { 170 | return stored == "true"; 171 | } 172 | }, 173 | initIsCompassFollowChecked: function () { 174 | const stored = localStorage.getItem("isCompassFollowChecked"); 175 | if (stored === null) { 176 | return true; 177 | } else { 178 | return stored == "true"; 179 | } 180 | }, 181 | initIsOpenMenuSoundsChecked: function () { 182 | const stored = localStorage.getItem("isOpenMenuSoundsChecked"); 183 | if (stored === null) { 184 | return true; 185 | } else { 186 | return stored == "true"; 187 | } 188 | }, 189 | initIsResetSoundsChecked: function () { 190 | const stored = localStorage.getItem("isResetSoundsChecked"); 191 | if (stored === null) { 192 | return true; 193 | } else { 194 | return stored == "true"; 195 | } 196 | }, 197 | initIsListSoundsChecked: function () { 198 | const stored = localStorage.getItem("isListSoundsChecked"); 199 | if (stored === null) { 200 | return true; 201 | } else { 202 | return stored == "true"; 203 | } 204 | }, 205 | initIsMapNotifChecked: function () { 206 | const stored = localStorage.getItem("isMapNotifChecked"); 207 | if (stored === null) { 208 | return true; 209 | } else { 210 | return stored == "true"; 211 | } 212 | }, 213 | initIsLowFuelChecked: function () { 214 | const stored = localStorage.getItem("isLowFuelChecked"); 215 | if (stored === null) { 216 | return true; 217 | } else { 218 | return stored == "true"; 219 | } 220 | }, 221 | initIsCinematicNotifChecked: function () { 222 | const stored = localStorage.getItem("isCinematicNotifChecked"); 223 | if (stored === null) { 224 | return true; 225 | } else { 226 | return stored == "true"; 227 | } 228 | }, 229 | initIsDynamicHealthChecked: function () { 230 | const stored = localStorage.getItem("isDynamicHealthChecked"); 231 | if (stored === null) { 232 | return false; 233 | } else { 234 | return stored == "true"; 235 | } 236 | }, 237 | initIsDynamicArmorChecked: function () { 238 | const stored = localStorage.getItem("isDynamicArmorChecked"); 239 | if (stored === null) { 240 | return false; 241 | } else { 242 | return stored == "true"; 243 | } 244 | }, 245 | initIsDynamicHungerChecked: function () { 246 | const stored = localStorage.getItem("isDynamicHungerChecked"); 247 | if (stored === null) { 248 | return false; 249 | } else { 250 | return stored == "true"; 251 | } 252 | }, 253 | initIsDynamicThirstChecked: function () { 254 | const stored = localStorage.getItem("isDynamicThirstChecked"); 255 | if (stored === null) { 256 | return false; 257 | } else { 258 | return stored == "true"; 259 | } 260 | }, 261 | initIsDynamicStressChecked: function () { 262 | const stored = localStorage.getItem("isDynamicStressChecked"); 263 | if (stored === null) { 264 | return false; 265 | } else { 266 | return stored == "true"; 267 | } 268 | }, 269 | initIsDynamicOxygenChecked: function () { 270 | const stored = localStorage.getItem("isDynamicOxygenChecked"); 271 | if (stored === null) { 272 | return false; 273 | } else { 274 | return stored == "true"; 275 | } 276 | }, 277 | initIsChangeFPSChecked: function () { 278 | const stored = localStorage.getItem("isChangeFPSChecked"); 279 | if (stored === null) { 280 | return "Optimized"; 281 | } else { 282 | return stored; 283 | } 284 | }, 285 | initIsToggleMapShapeChecked: function () { 286 | const stored = localStorage.getItem("isToggleMapShapeChecked"); 287 | if (stored === null) { 288 | return "Circle"; 289 | } else { 290 | return stored; 291 | } 292 | }, 293 | initIsHideMapChecked: function () { 294 | const stored = localStorage.getItem("isHideMapChecked"); 295 | if (stored === null) { 296 | return true; 297 | } else { 298 | return stored == "true"; 299 | } 300 | }, 301 | initIsToggleMapBordersChecked: function () { 302 | const stored = localStorage.getItem("isToggleMapBordersChecked"); 303 | if (stored === null) { 304 | return true; 305 | } else { 306 | return stored == "true"; 307 | } 308 | }, 309 | initIsDynamicEngineChecked: function () { 310 | const stored = localStorage.getItem("isDynamicEngineChecked"); 311 | if (stored === null) { 312 | return false; 313 | } else { 314 | return stored == "true"; 315 | } 316 | }, 317 | initIsDynamicNitroChecked: function () { 318 | const stored = localStorage.getItem("isDynamicNitroChecked"); 319 | if (stored === null) { 320 | return false; 321 | } else { 322 | return stored == "true"; 323 | } 324 | }, 325 | initIsChangeCompassFPSChecked: function () { 326 | const stored = localStorage.getItem("isChangeCompassFPSChecked"); 327 | if (stored === null) { 328 | return "Optimized"; 329 | } else { 330 | return stored; 331 | } 332 | }, 333 | initIsShowCompassChecked: function () { 334 | const stored = localStorage.getItem("isShowCompassChecked"); 335 | if (stored === null) { 336 | return true; 337 | } else { 338 | return stored == "true"; 339 | } 340 | }, 341 | initIsShowStreetsChecked: function () { 342 | const stored = localStorage.getItem("isShowStreetsChecked"); 343 | if (stored === null) { 344 | return true; 345 | } else { 346 | return stored == "true"; 347 | } 348 | }, 349 | initIsPointerShowChecked: function () { 350 | const stored = localStorage.getItem("isPointerShowChecked"); 351 | if (stored === null) { 352 | return true; 353 | } else { 354 | return stored == "true"; 355 | } 356 | }, 357 | initIsDegreesShowChecked: function () { 358 | const stored = localStorage.getItem("isDegreesShowChecked"); 359 | if (stored === null) { 360 | return true; 361 | } else { 362 | return stored == "true"; 363 | } 364 | }, 365 | initisCinematicModeChecked: function () { 366 | const stored = localStorage.getItem("isCinematicModeChecked"); 367 | if (stored === null) { 368 | return false; 369 | } else { 370 | return stored == "true"; 371 | } 372 | }, 373 | resetStorage: function (event) { 374 | targetId = event.currentTarget.id; 375 | localStorage.clear(); 376 | resetStorage(); 377 | }, 378 | restartHud: function (event) { 379 | targetId = event.currentTarget.id; 380 | restartHud(); 381 | }, 382 | showOutMap: function (event) { 383 | targetId = event.currentTarget.id; 384 | showOutMap(); 385 | }, 386 | showOutCompass: function (event) { 387 | targetId = event.currentTarget.id; 388 | showOutCompass(); 389 | }, 390 | showFollowCompass: function (event) { 391 | targetId = event.currentTarget.id; 392 | showFollowCompass(); 393 | }, 394 | openMenuSounds: function (event) { 395 | targetId = event.currentTarget.id; 396 | openMenuSounds(); 397 | }, 398 | resetHudSounds: function (event) { 399 | targetId = event.currentTarget.id; 400 | resetHudSounds(); 401 | }, 402 | checklistSounds: function (event) { 403 | targetId = event.currentTarget.id; 404 | checklistSounds(); 405 | }, 406 | showMapNotif: function (event) { 407 | targetId = event.currentTarget.id; 408 | showMapNotif(); 409 | }, 410 | showFuelAlert: function (event) { 411 | targetId = event.currentTarget.id; 412 | showFuelAlert(); 413 | }, 414 | showCinematicNotif: function (event) { 415 | targetId = event.currentTarget.id; 416 | showCinematicNotif(); 417 | }, 418 | dynamicHealth: function (event) { 419 | targetId = event.currentTarget.id; 420 | dynamicHealth(); 421 | }, 422 | dynamicArmor: function (event) { 423 | targetId = event.currentTarget.id; 424 | dynamicArmor(); 425 | }, 426 | dynamicHunger: function (event) { 427 | targetId = event.currentTarget.id; 428 | dynamicHunger(); 429 | }, 430 | dynamicThirst: function (event) { 431 | targetId = event.currentTarget.id; 432 | dynamicThirst(); 433 | }, 434 | dynamicStress: function (event) { 435 | targetId = event.currentTarget.id; 436 | dynamicStress(); 437 | }, 438 | dynamicOxygen: function (event) { 439 | targetId = event.currentTarget.id; 440 | dynamicOxygen(); 441 | }, 442 | changeFPS: function (event) { 443 | targetId = event.currentTarget.id; 444 | changeFPS(); 445 | }, 446 | ToggleMapShape: function (event) { 447 | targetId = event.currentTarget.id; 448 | ToggleMapShape(); 449 | }, 450 | HideMap: function (event) { 451 | targetId = event.currentTarget.id; 452 | HideMap(); 453 | }, 454 | ToggleMapBorders: function (event) { 455 | targetId = event.currentTarget.id; 456 | ToggleMapBorders(); 457 | }, 458 | dynamicEngine: function (event) { 459 | targetId = event.currentTarget.id; 460 | dynamicEngine(); 461 | }, 462 | dynamicNitro: function (event) { 463 | targetId = event.currentTarget.id; 464 | dynamicNitro(); 465 | }, 466 | changeCompassFPS: function (event) { 467 | targetId = event.currentTarget.id; 468 | changeCompassFPS(); 469 | }, 470 | showCompassBase: function (event) { 471 | targetId = event.currentTarget.id; 472 | showCompassBase(); 473 | }, 474 | showStreetsNames: function (event) { 475 | targetId = event.currentTarget.id; 476 | showStreetsNames(); 477 | }, 478 | showPointerIndex: function (event) { 479 | targetId = event.currentTarget.id; 480 | showPointerIndex(); 481 | }, 482 | showDegreesNum: function (event) { 483 | targetId = event.currentTarget.id; 484 | showDegreesNum(); 485 | }, 486 | cinematicMode: function (event) { 487 | targetId = event.currentTarget.id; 488 | cinematicMode(); 489 | }, 490 | }, 491 | mounted() { 492 | this.listener = window.addEventListener("message", (event) => { 493 | if (event.data.event === "isToggleMapShapeChecked" || event.data.event === "isChangeFPSChecked") { 494 | eval(`this.${event.data.event} = "${event.data.toggle}"`); 495 | } 496 | }); 497 | }, 498 | }); 499 | 500 | app.use(Quasar, { config: {} }); 501 | app.mount("#menu"); 502 | 503 | document.onkeyup = function (data) { 504 | if (data.key == "Escape") { 505 | closeMenu(); 506 | } 507 | }; 508 | 509 | function closeMenu() { 510 | $("#openmenu").fadeOut(550); 511 | $.post("https://qb-hud/closeMenu"); 512 | } 513 | function restartHud() { 514 | closeMenu(); 515 | $.post("https://qb-hud/restartHud"); 516 | } 517 | function resetStorage() { 518 | closeMenu(); 519 | $.post("https://qb-hud/resetStorage"); 520 | } 521 | function showOutMap() { 522 | $.post("https://qb-hud/showOutMap"); 523 | } 524 | function showOutCompass() { 525 | $.post("https://qb-hud/showOutCompass"); 526 | } 527 | function showFollowCompass() { 528 | $.post("https://qb-hud/showFollowCompass"); 529 | } 530 | function openMenuSounds() { 531 | $.post("https://qb-hud/openMenuSounds"); 532 | } 533 | function resetHudSounds() { 534 | $.post("https://qb-hud/resetHudSounds"); 535 | } 536 | function checklistSounds() { 537 | $.post("https://qb-hud/checklistSounds"); 538 | } 539 | function showMapNotif() { 540 | $.post("https://qb-hud/showMapNotif"); 541 | } 542 | function showFuelAlert() { 543 | $.post("https://qb-hud/showFuelAlert"); 544 | } 545 | function showCinematicNotif() { 546 | $.post("https://qb-hud/showCinematicNotif"); 547 | } 548 | function dynamicHealth() { 549 | $.post("https://qb-hud/dynamicHealth"); 550 | } 551 | function dynamicArmor() { 552 | $.post("https://qb-hud/dynamicArmor"); 553 | } 554 | function dynamicHunger() { 555 | $.post("https://qb-hud/dynamicHunger"); 556 | } 557 | function dynamicThirst() { 558 | $.post("https://qb-hud/dynamicThirst"); 559 | } 560 | function dynamicStress() { 561 | $.post("https://qb-hud/dynamicStress"); 562 | } 563 | function dynamicOxygen() { 564 | $.post("https://qb-hud/dynamicOxygen"); 565 | } 566 | function dynamicEngine() { 567 | $.post("https://qb-hud/dynamicEngine"); 568 | } 569 | function dynamicNitro() { 570 | $.post("https://qb-hud/dynamicNitro"); 571 | } 572 | function ToggleMapShape() { 573 | $.post("https://qb-hud/ToggleMapShape"); 574 | } 575 | function changeFPS() { 576 | $.post("https://qb-hud/changeFPS"); 577 | } 578 | function ToggleMapBorders() { 579 | $.post("https://qb-hud/ToggleMapBorders"); 580 | } 581 | function HideMap() { 582 | $.post("https://qb-hud/HideMap"); 583 | } 584 | function changeCompassFPS() { 585 | $.post("https://qb-hud/changeCompassFPS"); 586 | } 587 | function showCompassBase() { 588 | $.post("https://qb-hud/showCompassBase"); 589 | } 590 | function showStreetsNames() { 591 | $.post("https://qb-hud/showStreetsNames"); 592 | } 593 | function showPointerIndex() { 594 | $.post("https://qb-hud/showPointerIndex"); 595 | } 596 | function showDegreesNum() { 597 | $.post("https://qb-hud/showDegreesNum"); 598 | } 599 | function cinematicMode() { 600 | $.post("https://qb-hud/cinematicMode"); 601 | } 602 | 603 | $(document).ready(function () { 604 | window.addEventListener("message", function (event) { 605 | switch (event.data.action) { 606 | case "open": 607 | Open(event.data); 608 | break; 609 | } 610 | }); 611 | }); 612 | 613 | Open = function (data) { 614 | $("#openmenu").fadeIn(150); 615 | }; 616 | $(".closeMenu").click(() => { 617 | closeMenu(); 618 | }); 619 | 620 | // MONEY HUD 621 | 622 | const moneyHud = Vue.createApp({ 623 | data() { 624 | return { 625 | cash: 0, 626 | bank: 0, 627 | amount: 0, 628 | plus: false, 629 | minus: false, 630 | showCash: false, 631 | showBank: false, 632 | showUpdate: false, 633 | }; 634 | }, 635 | destroyed() { 636 | window.removeEventListener("message", this.listener); 637 | }, 638 | mounted() { 639 | this.listener = window.addEventListener("message", (event) => { 640 | switch (event.data.action) { 641 | case "showconstant": 642 | this.showConstant(event.data); 643 | break; 644 | case "updatemoney": 645 | this.update(event.data); 646 | break; 647 | case "show": 648 | this.showAccounts(event.data); 649 | break; 650 | } 651 | }); 652 | }, 653 | methods: { 654 | // CONFIGURE YOUR CURRENCY HERE 655 | // https://www.w3schools.com/tags/ref_language_codes.asp LANGUAGE CODES 656 | // https://www.w3schools.com/tags/ref_country_codes.asp COUNTRY CODES 657 | formatMoney(value) { 658 | const formatter = new Intl.NumberFormat("en-US", { 659 | style: "currency", 660 | currency: "USD", 661 | minimumFractionDigits: 0, 662 | }); 663 | return formatter.format(value); 664 | }, 665 | showConstant(data) { 666 | this.showCash = true; 667 | this.showBank = true; 668 | this.cash = data.cash; 669 | this.bank = data.bank; 670 | }, 671 | update(data) { 672 | this.showUpdate = true; 673 | this.amount = data.amount; 674 | this.bank = data.bank; 675 | this.cash = data.cash; 676 | this.minus = data.minus; 677 | this.plus = data.plus; 678 | if (data.type === "cash") { 679 | if (data.minus) { 680 | this.showCash = true; 681 | this.minus = true; 682 | setTimeout(() => (this.showUpdate = false), 1000); 683 | setTimeout(() => (this.showCash = false), 2000); 684 | } else { 685 | this.showCash = true; 686 | this.plus = true; 687 | setTimeout(() => (this.showUpdate = false), 1000); 688 | setTimeout(() => (this.showCash = false), 2000); 689 | } 690 | } 691 | if (data.type === "bank") { 692 | if (data.minus) { 693 | this.showBank = true; 694 | this.minus = true; 695 | setTimeout(() => (this.showUpdate = false), 1000); 696 | setTimeout(() => (this.showBank = false), 2000); 697 | } else { 698 | this.showBank = true; 699 | this.plus = true; 700 | setTimeout(() => (this.showUpdate = false), 1000); 701 | setTimeout(() => (this.showBank = false), 2000); 702 | } 703 | } 704 | }, 705 | showAccounts(data) { 706 | if (data.type === "cash" && !this.showCash) { 707 | this.showCash = true; 708 | this.cash = data.cash; 709 | setTimeout(() => (this.showCash = false), 3500); 710 | } else if (data.type === "bank" && !this.showBank) { 711 | this.showBank = true; 712 | this.bank = data.bank; 713 | setTimeout(() => (this.showBank = false), 3500); 714 | } 715 | }, 716 | }, 717 | }).mount("#money-container"); 718 | 719 | // PLAYER HUD 720 | 721 | const playerHud = { 722 | data() { 723 | return { 724 | dynamicHealth: 0, 725 | dynamicHunger: 0, 726 | dynamicThirst: 0, 727 | dynamicStress: 0, 728 | dynamicOxygen: 0, 729 | dynamicEngine: 0, 730 | dynamicNitro: 0, 731 | nos: 0, 732 | static: 100, 733 | health: 0, 734 | playerDead: 0, 735 | armor: 0, 736 | hunger: 0, 737 | thirst: 0, 738 | stress: 0, 739 | voice: 0, 740 | radio: 0, 741 | harness: 0, 742 | nitroActive: 0, 743 | cruise: 0, 744 | parachute: 0, 745 | oxygen: 0, 746 | hp: 0, 747 | armed: 0, 748 | speed: 0, 749 | engine: 0, 750 | cinematic: 0, 751 | dev: 0, 752 | show: false, 753 | talking: false, 754 | showVoice: true, 755 | showHealth: false, 756 | showArmor: true, 757 | showHunger: true, 758 | showThirst: true, 759 | showNos: true, 760 | showStress: true, 761 | showOxygen: false, 762 | showArmed: true, 763 | showEngine: false, 764 | showCruise: false, 765 | showHarness: false, 766 | showParachute: false, 767 | showDev: false, 768 | voiceIcon: "fas fa-microphone", 769 | talkingColor: "#FFFFFF", 770 | nosColor: "", 771 | engineColor: "", 772 | armorColor: "", 773 | hungerColor: "", 774 | healthColor: "", 775 | thirstColor: "", 776 | radioActive: false, 777 | }; 778 | }, 779 | 780 | destroyed() { 781 | window.removeEventListener("message", this.listener); 782 | }, 783 | mounted() { 784 | this.listener = window.addEventListener("message", (event) => { 785 | if (event.data.action === "hudtick") { 786 | this.hudTick(event.data); 787 | } 788 | // else if(event.data.update) { 789 | // eval(event.data.action + "(" + event.data.show + ')') 790 | // } 791 | }); 792 | Config = {}; 793 | }, 794 | methods: { 795 | hudTick(data) { 796 | this.show = data.show; 797 | this.health = data.health; 798 | this.armor = data.armor; 799 | this.hunger = data.hunger; 800 | this.thirst = data.thirst; 801 | this.stress = data.stress; 802 | this.voice = data.voice; 803 | this.talking = data.talking; 804 | this.radio = data.radio; 805 | this.radioActive = data.radioActive; 806 | this.nos = data.nos; 807 | this.oxygen = data.oxygen; 808 | this.cruise = data.cruise; 809 | this.nitroActive = data.nitroActive; 810 | this.harness = data.harness; 811 | this.speed = data.speed; 812 | this.armed = data.armed; 813 | this.parachute = data.parachute; 814 | this.hp = data.hp * 5; 815 | this.engine = data.engine; 816 | this.cinematic = data.cinematic; 817 | this.dev = data.dev; 818 | this.playerDead = data.playerDead; 819 | this.dynamicHealth = data.dynamicHealth; 820 | this.dynamicArmor = data.dynamicArmor; 821 | this.dynamicHunger = data.dynamicHunger; 822 | this.dynamicThirst = data.dynamicThirst; 823 | this.dynamicStress = data.dynamicStress; 824 | this.dynamicOxygen = data.dynamicOxygen; 825 | this.dynamicEngine = data.dynamicEngine; 826 | this.dynamicNitro = data.dynamicNitro; 827 | 828 | if (data.dynamicHealth == true) { 829 | if (data.health >= 100) { 830 | this.showHealth = false; 831 | } else { 832 | this.showHealth = true; 833 | } 834 | } else if (data.dynamicHealth == false) { 835 | this.showHealth = true; 836 | } 837 | if (data.playerDead === false) { 838 | this.healthColor = "#3FA554"; 839 | } else { 840 | this.healthColor = "#ff0000"; 841 | this.health = 100; 842 | } 843 | 844 | if (data.dynamicArmor == true) { 845 | if (data.armor == 0) { 846 | this.showArmor = false; 847 | } else { 848 | this.showArmor = true; 849 | } 850 | } else if (data.dynamicArmor == false) { 851 | this.showArmor = true; 852 | } 853 | 854 | if (data.armor <= 0) { 855 | this.armorColor = "#FF0000"; 856 | } else { 857 | this.armorColor = "#326dbf"; 858 | } 859 | 860 | if (data.dynamicHunger == true) { 861 | if (data.hunger >= 100) { 862 | this.showHunger = false; 863 | } else { 864 | this.showHunger = true; 865 | } 866 | } else if (data.dynamicHunger == false) { 867 | this.showHunger = true; 868 | } 869 | if (data.hunger >= 100) { 870 | this.hungerColor = "#dd6e14"; 871 | } else if (data.hunger <= 30) { 872 | this.hungerColor = "#ff0000"; 873 | } else { 874 | this.hungerColor = "#dd6e14"; 875 | } 876 | 877 | if (data.dynamicThirst == true) { 878 | if (data.thirst >= 100) { 879 | this.showThirst = false; 880 | } else { 881 | this.showThirst = true; 882 | } 883 | } else if (data.dynamicThirst == false) { 884 | this.showThirst = true; 885 | } 886 | if (data.thirst >= 100) { 887 | this.thirstColor = "#1a7cad"; 888 | } else if (data.thirst <= 30) { 889 | this.thirstColor = "#ff0000"; 890 | } else { 891 | this.thirstColor = "#1a7cad"; 892 | } 893 | 894 | if (data.dynamicStress == true) { 895 | if (data.stress == 0) { 896 | this.showStress = false; 897 | } else { 898 | this.showStress = true; 899 | } 900 | } else if (data.dynamicStress == false) { 901 | this.showStress = true; 902 | } 903 | 904 | if (data.dynamicOxygen == true) { 905 | if (data.oxygen >= 100) { 906 | this.showOxygen = false; 907 | } else { 908 | this.showOxygen = true; 909 | } 910 | } else if (data.dynamicOxygen == false) { 911 | this.showOxygen = true; 912 | } 913 | 914 | if (data.dynamicEngine == true) { 915 | if (data.engine >= 95) { 916 | this.showEngine = false; 917 | } else if (data.engine < 0) { 918 | this.showEngine = false; 919 | } else { 920 | this.showEngine = true; 921 | } 922 | } else if (data.dynamicEngine == false) { 923 | if (data.engine < 0) { 924 | this.showEngine = false; 925 | } else { 926 | this.showEngine = true; 927 | } 928 | } 929 | if (data.engine <= 45) { 930 | this.engineColor = "#ff0000"; 931 | } else if (data.engine <= 75 && data.engine >= 46) { 932 | this.engineColor = "#dd6e14"; 933 | } else if (data.engine <= 100) { 934 | this.engineColor = "#3FA554"; 935 | } 936 | 937 | if (data.dynamicNitro == true) { 938 | if (data.nos === 0 || data.nos === undefined) { 939 | this.showNos = false; 940 | } else if (data.nos < 0) { 941 | this.showNos = false; 942 | } else { 943 | this.showNos = true; 944 | } 945 | } else if (data.dynamicNitro == false) { 946 | if (data.nos < 0) { 947 | this.showNos = false; 948 | } else { 949 | this.showNos = true; 950 | } 951 | } 952 | if (data.nitroActive) { 953 | this.nosColor = "#D64763"; 954 | } else { 955 | this.nosColor = "#FFFFFF"; 956 | } 957 | 958 | if (data.radioActive) { 959 | this.talkingColor = "#D64763"; 960 | } else if (data.talking) { 961 | this.talkingColor = "#FFFF3E"; 962 | } else { 963 | this.talkingColor = "#FFFFFF"; 964 | } 965 | if (data.radio != 0 && data.radio != undefined) { 966 | this.voiceIcon = "fas fa-headset"; 967 | } else if (data.radio == 0 || data.radio == undefined) { 968 | this.voiceIcon = "fas fa-microphone"; 969 | } 970 | if (data.cruise === true) { 971 | this.cruise = 1; 972 | this.showCruise = true; 973 | } else { 974 | this.cruise = 0; 975 | this.showCruise = false; 976 | } 977 | 978 | if (data.harness === true) { 979 | this.showHarness = true; 980 | } else { 981 | this.showHarness = false; 982 | } 983 | if (data.armed === true) { 984 | this.showArmed = true; 985 | } else { 986 | this.showArmed = false; 987 | } 988 | 989 | if (data.parachute >= 0) { 990 | this.showParachute = true; 991 | } else { 992 | this.showParachute = false; 993 | } 994 | 995 | if (data.dev === true) { 996 | this.showDev = true; 997 | } else { 998 | this.showDev = false; 999 | } 1000 | 1001 | if (data.isPaused === 1) { 1002 | this.show = false; 1003 | } 1004 | }, 1005 | }, 1006 | }; 1007 | const app2 = Vue.createApp(playerHud); 1008 | app2.use(Quasar); 1009 | app2.mount("#ui-container"); 1010 | 1011 | // VEHICLE HUD 1012 | 1013 | const vehHud = { 1014 | data() { 1015 | return { 1016 | speedometer: 66, 1017 | fuelgauge: 69, 1018 | altitudegauge: 75, 1019 | fuel: 0, 1020 | speed: 0, 1021 | seatbelt: 0, 1022 | showSquareB: 0, 1023 | show: false, 1024 | showAltitude: true, 1025 | showSeatbelt: true, 1026 | showSquare: false, 1027 | showCircle: false, 1028 | seatbeltColor: "", 1029 | }; 1030 | }, 1031 | 1032 | destroyed() { 1033 | window.removeEventListener("message", this.listener); 1034 | }, 1035 | mounted() { 1036 | this.listener = window.addEventListener("message", (event) => { 1037 | if (event.data.action === "car") { 1038 | this.vehicleHud(event.data); 1039 | } 1040 | }); 1041 | }, 1042 | methods: { 1043 | vehicleHud(data) { 1044 | this.show = data.show; 1045 | this.speed = data.speed; 1046 | this.altitude = data.altitude; 1047 | this.fuel = data.fuel * 0.71; 1048 | this.showSeatbelt = data.showSeatbelt; 1049 | this.showAltitude = data.showAltitude; 1050 | this.showSquareB = data.showSquareB; 1051 | this.showCircleB = data.showCircleB; 1052 | if (data.seatbelt === true) { 1053 | this.seatbelt = 1; 1054 | this.seatbeltColor = "transparent"; 1055 | } else { 1056 | this.seatbelt = 0; 1057 | this.seatbeltColor = "#FF5100"; 1058 | } 1059 | if (data.showSeatbelt === true) { 1060 | this.showSeatbelt = true; 1061 | } else { 1062 | this.showSeatbelt = false; 1063 | } 1064 | if (data.showAltitude === true) { 1065 | this.showAltitude = true; 1066 | } else { 1067 | this.showAltitude = false; 1068 | } 1069 | if (data.fuel <= 20) { 1070 | this.fuelColor = "#ff0000"; 1071 | } else if (data.fuel <= 30) { 1072 | this.fuelColor = "#dd6e14"; 1073 | } else { 1074 | this.fuelColor = "#FFFFFF"; 1075 | } 1076 | if (data.showSquareB === true) { 1077 | this.showSquare = true; 1078 | } else { 1079 | this.showSquare = false; 1080 | } 1081 | if (data.showCircleB === true) { 1082 | this.showCircle = true; 1083 | } else { 1084 | this.showCircle = false; 1085 | } 1086 | if (data.isPaused === 1) { 1087 | this.show = false; 1088 | } 1089 | }, 1090 | }, 1091 | }; 1092 | const app3 = Vue.createApp(vehHud); 1093 | app3.use(Quasar); 1094 | app3.mount("#veh-container"); 1095 | 1096 | // COMPASS HUD 1097 | 1098 | const baseplateHud = { 1099 | data() { 1100 | return { 1101 | show: false, 1102 | street1: "", 1103 | street2: "", 1104 | showCompass: true, 1105 | showStreets: true, 1106 | showPointer: true, 1107 | showDegrees: true, 1108 | }; 1109 | }, 1110 | destroyed() { 1111 | window.removeEventListener("message", this.listener); 1112 | }, 1113 | mounted() { 1114 | this.listener = window.addEventListener("message", (event) => { 1115 | if (event.data.action == "update") { 1116 | type = event.data.type; 1117 | value = event.data.value; 1118 | if (value !== undefined) { 1119 | $(".degrees").html(value); 1120 | bar = document.getElementsByTagName("svg")[0]; 1121 | bar.setAttribute("viewBox", "" + (value - 90) + " 0 180 5"); 1122 | heading = document.getElementsByTagName("svg")[1]; 1123 | heading.setAttribute("viewBox", "" + (value - 90) + " 0 180 1.5"); 1124 | } 1125 | } 1126 | if (event.data.action === "baseplate") { 1127 | this.baseplateHud(event.data); 1128 | } 1129 | }); 1130 | }, 1131 | methods: { 1132 | baseplateHud(data) { 1133 | this.show = data.show; 1134 | this.street1 = data.street1; 1135 | this.street2 = data.street2; 1136 | this.showCompass = data.showCompass; 1137 | this.showStreets = data.showStreets; 1138 | this.showPointer = data.showPointer; 1139 | this.showDegrees = data.showDegrees; 1140 | if (data.showCompass == true) { 1141 | this.showCompass = true; 1142 | } else { 1143 | this.showCompass = false; 1144 | } 1145 | if (data.showStreets == true) { 1146 | this.showStreets = true; 1147 | } else { 1148 | this.showStreets = false; 1149 | } 1150 | if (data.showPointer == true) { 1151 | this.showPointer = true; 1152 | } else { 1153 | this.showPointer = false; 1154 | } 1155 | if (data.showDegrees == true) { 1156 | this.showDegrees = true; 1157 | } else { 1158 | this.showDegrees = false; 1159 | } 1160 | }, 1161 | }, 1162 | }; 1163 | const app4 = Vue.createApp(baseplateHud); 1164 | app4.use(Quasar); 1165 | app4.mount("#baseplate-container"); 1166 | --------------------------------------------------------------------------------