Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hud remake #20

Closed
wants to merge 38 commits into from
Closed
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
85fa0fa
Hud remake
TonybynMp4 Jan 4, 2024
bf1edeb
en locale update
TonybynMp4 Jan 4, 2024
da5179b
fix ox_inventory event
TonybynMp4 Jan 4, 2024
6fe0348
unused variables
TonybynMp4 Jan 4, 2024
3813db2
fix linting?
TonybynMp4 Jan 5, 2024
095a595
Disable minimap on login
TonybynMp4 Jan 8, 2024
032c27c
localize playerstate & remove useless safe navigation
TonybynMp4 Jan 11, 2024
2d8461c
improved shooting stress loop
TonybynMp4 Jan 11, 2024
747bedd
prevent ram from going up (flextape style)
TonybynMp4 Jan 11, 2024
3678001
use native instead of state.fuel
TonybynMp4 Jan 11, 2024
ccac1de
improve voice loop, use proximity statebag & correctly calculate prox…
TonybynMp4 Jan 11, 2024
bfa0c20
config for new shooting loop
TonybynMp4 Jan 11, 2024
bacf6ab
rename global variable correctly
TonybynMp4 Jan 12, 2024
a5ec51c
feat: locales
TonybynMp4 Mar 16, 2024
153a75a
fixes (#2)
TonybynMp4 Mar 16, 2024
b4e31ba
feat: ox_lib locales
TonybynMp4 Mar 16, 2024
54bea20
Merge branch 'main' into dev
TonybynMp4 Mar 16, 2024
6ae4de6
feat: circular progressbars
TonybynMp4 Mar 25, 2024
a6d30bf
fix: stroke not BG
TonybynMp4 Mar 25, 2024
f4a7496
Merge branch 'main' into dev
TonybynMp4 Apr 5, 2024
976a9f4
Merge branch 'main' into dev
TonybynMp4 Apr 8, 2024
6170c04
add transition
TonybynMp4 Apr 25, 2024
a339004
fix: stream fonts
TonybynMp4 Apr 25, 2024
ac81c9b
split in multiple files & localize frequently used natives
TonybynMp4 Apr 25, 2024
274019e
move to the main thread
TonybynMp4 Apr 25, 2024
9fed10a
how did that get here
TonybynMp4 Apr 25, 2024
2b9b414
fixes
TonybynMp4 Apr 25, 2024
0a4a7a1
feat: marker on voice change
TonybynMp4 Apr 30, 2024
2a4ff94
drop support for onMoneyChange, bank changes should be handled by the…
TonybynMp4 May 6, 2024
2c5d1e2
move the progress styling entirely to the JS
TonybynMp4 May 6, 2024
4bb9343
extract stress function
TonybynMp4 May 6, 2024
86646e5
fix: typo
TonybynMp4 May 7, 2024
d9c2d9b
remove the UI money stuff
TonybynMp4 May 7, 2024
21b74a2
fix: rework Mph config & indicators
TonybynMp4 May 7, 2024
31e0e47
fix: changed var
TonybynMp4 May 7, 2024
36fc2f7
fix: speed isn't set if above the estimated maxspeed
TonybynMp4 May 7, 2024
b139210
fix: might want round it BEFORE using it
TonybynMp4 May 7, 2024
9e1801d
rotaté
TonybynMp4 May 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
##
**Q:** How do I enable dev mode?

**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
**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
##

##
70 changes: 70 additions & 0 deletions client/compass.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
local SendNUIMessage = SendNUIMessage
local currentHeading
local currentStreet
local currentStreet2
local showingMinimap = false
local directions = {
N = 360,
NE = 315,
E = 270,
SE = 225,
S = 180,
SW = 135,
W = 90,
NW = 45,
}

CreateThread(function()
Wait(250)
while true do
local sleep = 1000
if not IsMinimapRendering() then
if showingMinimap then
showingMinimap = false
SendNUIMessage({
update = true,
data = {
{
type = 'compass',
show = false,
}
}
})
end
else
local coords = GetEntityCoords(cache.ped)
local var1, var2 = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
local street, hash2 = GetStreetNameFromHashKey(var1), GetStreetNameFromHashKey(var2)
local street2 = ("%s%s"):format(hash2 ~= '' and hash2 .. ', ' or '', GetLabelText(GetNameOfZone(coords.x, coords.y, coords.z)))
local heading = GetEntityHeading(cache.ped) % 360
local convertedHeading = 'N'

for k, v in pairs(directions) do
if heading >= v - 22.5 and heading <= v + 22.5 then
convertedHeading = k
break
end
end

if currentHeading ~= convertedHeading or currentStreet ~= street or currentStreet2 ~= street2 then
SendNUIMessage({
update = true,
data = {
{
type = 'compass',
show = true,
heading = currentHeading ~= convertedHeading and convertedHeading or nil,
street = currentStreet ~= street and street or nil,
street2 = currentStreet2 ~= street2 and street2 or nil,
}
}
})
currentHeading, currentStreet, currentStreet2 = convertedHeading, street, street2
showingMinimap = true
end
sleep = 500
--collectgarbage() -- please help i don't understand why this is necessary
end
Wait(sleep)
end
end)
1,117 changes: 95 additions & 1,022 deletions client/main.lua

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions client/player.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
AddStateBagChangeHandler('hunger', ('player:%s'):format(cache.serverId), function(_, _, value)
if value == PlayerState.hunger then return end
SendNUIMessage({
update = true,
data = {
{
type = 'progress',
name = 'hunger',
value = value
}
}
})
end)

AddStateBagChangeHandler('thirst', ('player:%s'):format(cache.serverId), function(_, _, value)
if value == PlayerState.thirst then return end
SendNUIMessage({
update = true,
data = {
{
type = 'progress',
name = 'thirst',
value = value
}
}
})
end)

AddStateBagChangeHandler('stress', ('player:%s'):format(cache.serverId), function(_, _, value)
if value == Stress then return end
Stress = value

SendNUIMessage({
update = true,
data = {
{
type = 'progress',
name = 'stress',
value = value
}
}
})
end)
100 changes: 100 additions & 0 deletions client/stress.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
local config = require("config.client")
local stressConfig = config.stress
Stress = PlayerState.stress or 0
local SPEED_MULTIPLIER = config.useMPH and 2.236936 or 3.6

-- Stress Gain
CreateThread(function() -- Speeding
while true do
if PlayerState.isLoggedIn then
if cache.vehicle and not PlayerState.harness and GetVehicleClass(cache.vehicle) ~= 8 then
local speed = GetEntitySpeed(cache.vehicle) * SPEED_MULTIPLIER
local stressSpeed = PlayerState.seatbelt and stressConfig.speedingMini or stressConfig.speedingUnbuckledMini
if speed >= stressSpeed then
TriggerServerEvent('hud:server:GainStress', math.random(stressConfig.speedingStress.min, stressConfig.speedingStress.max))
end
end
end
Wait(10000)
end
end)

local function armedLoop()
while cache.weapon do
if IsPedShooting(cache.ped) then
if math.random() < stressConfig.stressChance then
TriggerServerEvent('hud:server:GainStress', math.random(1, 3))
end
end
Wait(0)
end
end

lib.onCache('weapon', function(weapon)
if weapon and not config.whitelistedWeaponStress[weapon] then
CreateThread(armedLoop)
end
end)

-- Stress Screen Effects
local function GetBlurIntensity(stresslevel)
for _, v in pairs(stressConfig.intensity) do
if stresslevel >= v.min and stresslevel <= v.max then
return v.intensity
end
end
return 1500
end

local function GetEffectInterval(stresslevel)
for _, v in pairs(stressConfig.effectInterval) do
if stresslevel >= v.min and stresslevel <= v.max then
return v.timeout
end
end
return 60000
end

CreateThread(function()
while true do
local effectInterval = 2500
if PlayerState.isLoggedIn then
effectInterval = GetEffectInterval(Stress)
if Stress >= 100 then
local BlurIntensity = GetBlurIntensity(Stress)
local FallRepeat = math.random(2, 4)
local RagdollTimeout = FallRepeat * 1750
TriggerScreenblurFadeIn(1000.0)
Wait(BlurIntensity)
TriggerScreenblurFadeOut(1000.0)

if not cache.vehicle and not IsPedRagdoll(cache.ped) and IsPedOnFoot(cache.ped) and not IsPedSwimming(cache.ped) then
local forwardVec3 = GetEntityForwardVector(cache.ped)
SetPedToRagdollWithFall(cache.ped, RagdollTimeout, RagdollTimeout, 1, forwardVec3.x, forwardVec3.y, forwardVec3.z, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
end

Wait(1000)
for _ = 1, FallRepeat, 1 do
Wait(750)
TriggerScreenblurFadeIn(1000.0)
Wait(BlurIntensity)
TriggerScreenblurFadeOut(1000.0)
Wait(750)
TriggerScreenblurFadeIn(1000.0)
Wait(BlurIntensity)
TriggerScreenblurFadeOut(1000.0)
Wait(750)
TriggerScreenblurFadeIn(1000.0)
Wait(BlurIntensity)
TriggerScreenblurFadeOut(1000.0)
end
elseif Stress >= stressConfig.stressBlurMini then
local BlurIntensity = GetBlurIntensity(Stress)
TriggerScreenblurFadeIn(1000.0)
Wait(BlurIntensity)
TriggerScreenblurFadeOut(1000.0)
end
end
Wait(effectInterval)
end
end)
245 changes: 245 additions & 0 deletions client/vehicle.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
local config = require 'config.client'
local currentindicatorL, currentindicatorR = false, false
local getEntitySpeed = GetEntitySpeed
local getVehicleFuelLevel = GetVehicleFuelLevel
local getIsVehicleEngineRunning = GetIsVehicleEngineRunning
local getVehicleLightsState = GetVehicleLightsState
local getVehicleTrailerVehicle = GetVehicleTrailerVehicle
local getVehicleIndicatorLights = GetVehicleIndicatorLights
local isMinimapRendering = IsMinimapRendering
local isControlJustPressed = IsControlJustPressed
local setVehicleIndicatorLights = SetVehicleIndicatorLights
local sendNUIMessage = SendNUIMessage
local SPEED_MULTIPLIER = config.useMPH and 2.236936 or 3.6

local function vehiclehudloop()
local currentindicators = getVehicleIndicatorLights(cache.vehicle)
local indl = currentindicators == 1 or currentindicators == 3
local indr = currentindicators == 2 or currentindicators == 3
local warning = false

CreateThread(function()
local sleep
while cache.seat == -1 do
sleep = 1000
if getIsVehicleEngineRunning(cache.vehicle) and isMinimapRendering() then
local HasTrailer, Trailer = getVehicleTrailerVehicle(cache.vehicle)
if not warning and isControlJustPressed(1, 174) then -- <- is pressed
indl = not indl
indr = false
end
if not warning and isControlJustPressed(1, 175) then -- -> is pressed
indr = not indr
indl = false
end
if isControlJustPressed(1, 173) then -- down is pressed
warning = not warning
indl = warning
indr = warning
end

if isMinimapRendering() and (currentindicatorL ~= indl or currentindicatorR ~= indr) then
currentindicatorL, currentindicatorR = indl, indr

setVehicleIndicatorLights(cache.vehicle, 1, indl)
setVehicleIndicatorLights(cache.vehicle, 0, indr)
if HasTrailer then
setVehicleIndicatorLights(Trailer, 1, indl)
setVehicleIndicatorLights(Trailer, 0, indr)
end

sendNUIMessage({
update = true,
data = {
{
type = 'dashboardlights',
indicatorL = indl,
indicatorR = indr,
}
}
})
end
sleep = 0
end
Wait(sleep)
end
end)

CreateThread(function()
local alert = 0
local sleep
local showingHud = true
while cache.vehicle do
local data
local engineIsRunning = getIsVehicleEngineRunning(cache.vehicle)
if showingHud and not engineIsRunning then
data = {
{
type = 'vehiclehud',
show = false
}
}
showingHud = false
end

sleep = 1000
if engineIsRunning and isMinimapRendering() then
showingHud = true
local _, highbeam, lowbeam = getVehicleLightsState(cache.vehicle)
data = {
{
type = 'vehiclehud',
show = true
},
{
type = 'speed',
speed = getEntitySpeed(cache.vehicle) * SPEED_MULTIPLIER
},
{
type = 'gauge',
name = 'fuel',
value = getVehicleFuelLevel(cache.vehicle) or 100
},
{
type = 'dashboardlights',
highbeam = highbeam,
lowbeam = lowbeam,
}
}


-- not ideal, the 1500 doesn't actually equal 150 seconds because of framerate
if config.lowFuelAlert and getVehicleFuelLevel(cache.vehicle) < config.lowFuelAlert then
if alert > 0 then
alert -= 1
else
alert = 1500
qbx.playAudio({
audioName = "CONFIRM_BEEP",
audioRef = 'HUD_MINI_GAME_SOUNDSET',
source = cache.vehicle
})
exports.qbx_core:Notify(locale("notify.low_fuel"), "error")
end
end
sleep = 100
end

if data then
sendNUIMessage({
update = true,
data = data
})
end
Wait(sleep)
end
end)
end

local function initVehicleHud()
local data = {
{
type = 'vehiclehud',
show = false
}
}

if cache.seat == -1 then
local nitroLevel = Entity(cache.vehicle).state.nitro or 0
data = {
{
type = 'gauge',
name = 'nitro',
value = nitroLevel,
show = nitroLevel > 0
},
{
type = 'speedmax',
speed = (GetVehicleEstimatedMaxSpeed(cache.vehicle) * SPEED_MULTIPLIER) * 1.75
}
}
vehiclehudloop()
end

sendNUIMessage({
update = true,
data = data
})
end

qbx.entityStateHandler('nitro', function(veh, _, value)
if veh ~= cache.vehicle then return end
sendNUIMessage({
update = true,
data = {
{
type = 'gauge',
name = 'nitro',
value = value,
show = value > 0
}
}
})
end)

lib.onCache('vehicle', function(value)
if not value then
PlayerState:set('seatbelt', false, true)
PlayerState:set('harness', false, true)
sendNUIMessage({
update = true,
data = {
{
type = 'vehiclehud',
show = false
},
{
type = 'seatbelt',
value = false,
}
}
})
end
if not config.minimapAlwaysOn then
DisplayRadar(value)
end
end)

lib.onCache('seat', function(seat)
if seat == -1 then
SetTimeout(250, initVehicleHud)
end
end)

CreateThread(function()
SetTimeout(250, initVehicleHud)
end)

local harnessOn = false
AddStateBagChangeHandler('seatbelt', ('player:%s'):format(cache.serverId), function(_, _, value)
if harnessOn then return end
sendNUIMessage({
update = true,
data = {
{
type = 'seatbelt',
value = value,
}
}
})
end)

AddStateBagChangeHandler('harness', ('player:%s'):format(cache.serverId), function(_, _, value)
harnessOn = value

sendNUIMessage({
update = true,
data = {
{
type = 'seatbelt',
value = value or seatbeltOn,
harness = value,
}
}
})
end)
70 changes: 70 additions & 0 deletions client/voice.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
local SendNUIMessage = SendNUIMessage
local MumbleIsPlayerTalking = MumbleIsPlayerTalking

--- Set the talking status
---@param talking boolean
local function setTalking(talking)
SendNUIMessage({
update = true,
data = {
{
type = 'progress',
name = 'voice',
state = PlayerState.radioActive and 2 or talking and 1 or 0
}
}
})
end

require '@pma-voice.shared'
local proximityLevels = Cfg.voiceModes or {}
local highestLevel
for i = 1, #proximityLevels do
if not highestLevel or proximityLevels[i][1] > highestLevel then
highestLevel = proximityLevels[i][1]
end
end

local shouldShowMarker = false
local function showMarker(distance)
shouldShowMarker = true
SetTimeout(500, function()
if LocalPlayer.state.proximity.distance == distance then
shouldShowMarker = false
end
end)
while shouldShowMarker do
Wait(0)
local coords = GetEntityCoords(cache.ped)
DrawMarker(1, coords.x, coords.y, coords.z - (cache.vehicle and 0.5 or 1), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, distance, distance, 0.6, 255, 147, 90, 200, false, true, 2, false, nil, nil, false)
end
end

AddStateBagChangeHandler('proximity', ('player:%s'):format(cache.serverId), function(_, _, value)
shouldShowMarker = false
SendNUIMessage({
update = true,
data = {
{
type = 'progress',
name = 'voice',
value = value.distance / highestLevel * 100
}
}
})
SetTimeout(50, function()
showMarker(value.distance)
end)
end)

local isTalking = false
CreateThread(function()
while true do
local talking = MumbleIsPlayerTalking(cache.playerId)
if isTalking ~= talking then
isTalking = talking
setTalking(talking)
end
Wait(125)
end
end)
150 changes: 79 additions & 71 deletions config/client.lua
Original file line number Diff line number Diff line change
@@ -1,72 +1,80 @@
return {
menuKey = 'I', -- Key to open the HUD menu
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)

stress = {
chance = 0.1, -- Percentage stress chance when shooting (0-1)
minForShaking = 50, -- Minimum stress level for screen shaking
minForSpeeding = 1000, -- Minimum stress level for speeding while buckled
minForSpeedingUnbuckled = 50, -- Minimum stress level for speeding while unbuckled
whitelistedWeapons = { -- Weapons which don't give stress
`weapon_petrolcan`,
`weapon_hazardcan`,
`weapon_fireextinguisher`,
},
blurIntensity = { -- Blur intensity for different stress levels
[1] = {min = 50, max = 60, intensity = 1500},
[2] = {min = 60, max = 70, intensity = 2000},
[3] = {min = 70, max = 80, intensity = 2500},
[4] = {min = 80, max = 90, intensity = 2700},
[5] = {min = 90, max = 100, intensity = 3000},
},
effectInterval = { -- Effect interval for different stress levels
[1] = {min = 50, max = 60, timeout = math.random(50000, 60000)},
[2] = {min = 60, max = 70, timeout = math.random(40000, 50000)},
[3] = {min = 70, max = 80, timeout = math.random(30000, 40000)},
[4] = {min = 80, max = 90, timeout = math.random(20000, 30000)},
[5] = {min = 90, max = 100, timeout = math.random(15000, 20000)},
},
},

weaponsArmedMode = { -- Weapons which won't trigger armed mode
-- Miscellaneous
`weapon_petrolcan`,
`weapon_hazardcan`,
`weapon_fireextinguisher`,
-- Melee
`weapon_dagger`,
`weapon_bat`,
`weapon_bottle`,
`weapon_crowbar`,
`weapon_flashlight`,
`weapon_golfclub`,
`weapon_hammer`,
`weapon_hatchet`,
`weapon_knuckle`,
`weapon_knife`,
`weapon_machete`,
`weapon_switchblade`,
`weapon_nightstick`,
`weapon_wrench`,
`weapon_battleaxe`,
`weapon_poolcue`,
`weapon_briefcase`,
`weapon_briefcase_02`,
`weapon_garbagebag`,
`weapon_handcuffs`,
`weapon_bread`,
`weapon_stone_hatchet`,
-- Throwables
`weapon_grenade`,
`weapon_bzgas`,
`weapon_molotov`,
`weapon_stickybomb`,
`weapon_proxmine`,
`weapon_snowball`,
`weapon_pipebomb`,
`weapon_ball`,
`weapon_smokegrenade`,
`weapon_flare`,
},

return {
useMPH = false,
whitelistedWeaponStress = {
[`weapon_unarmed`] = true,
[`weapon_flashlight`] = true,
[`weapon_petrolcan`] = true,
[`weapon_hazardcan`] = true,
[`weapon_fireextinguisher`] = true,
[`weapon_stungun`] = true,
[`weapon_ball`] = true,
[`weapon_snowball`] = true,
},
cinematicHeight = 0.15,
lowFuelAlert = 15,
minimapAlwaysOn = true,
stress = {
speedingMini = 180,
speedingUnbuckledMini = 75,
stressBlurMini = 40,
stressChance = 0.05,
speedingStress = {
min = 1,
max = 3,
},
intensity = {
{
min = 50,
max = 60,
intensity = 1500,
},
{
min = 60,
max = 70,
intensity = 2000,
},
{
min = 70,
max = 80,
intensity = 2500,
},
{
min = 80,
max = 90,
intensity = 2700,
},
{
min = 90,
max = 100,
intensity = 3000,
},
},
effectInterval = {
{
min = 50,
max = 60,
timeout = math.random(180000, 240000)
},
{
min = 60,
max = 70,
timeout = math.random(120000, 180000)
},
{
min = 70,
max = 80,
timeout = math.random(90000, 120000)
},
{
min = 80,
max = 90,
timeout = math.random(60000, 90000)
},
{
min = 90,
max = 100,
timeout = math.random(30000, 60000)
}
},
}
}
4 changes: 1 addition & 3 deletions config/server.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
return {
stress = {
disableForLEO = true, -- If true, it will disable stress for people in the leo job type
},
disablePoliceStress = false
}
28 changes: 0 additions & 28 deletions config/shared.lua

This file was deleted.

26 changes: 14 additions & 12 deletions fxmanifest.lua
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
fx_version 'cerulean'
game 'gta5'

description 'HUD for Qbox'
description 'qbx_hud'
repository 'https://github.com/Qbox-project/qbx_hud'
version '1.0.0'

ox_lib 'locale'

shared_scripts {
'@ox_lib/init.lua',
'@qbx_core/modules/lib.lua',
'@qbx_core/modules/lib.lua'
}

client_scripts {
'@qbx_core/modules/playerdata.lua',
'client/main.lua',
'client/*.lua',
}

server_script 'server/main.lua'
server_scripts {
'server/*.lua',
}

ui_page 'html/index.html'

files {
'html/*',
'html/index.html',
'html/styles.css',
'html/responsive.css',
'html/app.js',
'locales/*.json',
'config/client.lua',
'config/shared.lua',
'@pma-voice/shared.lua',
'html/*'
}

dependencies {
'ox_lib',
'qbx_core',
}

lua54 'yes'
use_experimental_fxv2_oal 'yes'
use_experimental_fxv2_oal 'yes'
Binary file added html/Oxygen-Bold.ttf
Binary file not shown.
Binary file added html/Oxygen-Regular.ttf
Binary file not shown.
1,098 changes: 0 additions & 1,098 deletions html/app.js

This file was deleted.

1,374 changes: 0 additions & 1,374 deletions html/brand-logo.svg

This file was deleted.

520 changes: 183 additions & 337 deletions html/index.html

Large diffs are not rendered by default.

373 changes: 0 additions & 373 deletions html/responsive.css

This file was deleted.

154 changes: 154 additions & 0 deletions html/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
let maxSpeedCounter = 350;

document.addEventListener("DOMContentLoaded", function () {
window.addEventListener("message", function (event) {
if (event.data.update == true) {
const Data = event.data.data;
for (let i = 0; i < Data.length; i++) {
const dataItem = Data[i];
switch (dataItem.type) {
case 'compass':
setCompass(dataItem.show, dataItem.heading, dataItem.street, dataItem.street2);
break;
case 'vehiclehud':
document.getElementsByClassName('vehicle-hud')[0].style.opacity = dataItem.show ? 1 : 0;
break;
case 'speed':
setSpeed(dataItem.speed);
break;
case 'speedmax':
maxSpeedCounter = dataItem.speed;
break;
case 'gauge':
setGauge(dataItem.value, dataItem.name, dataItem.show);
break;
case 'dashboardlights':
setDashboardLight(dataItem);
break;
case 'progress':
let options = {};
switch (dataItem.name) {
case 'hunger':
options.stroke = dataItem.value < 30;
case 'thirst':
options.stroke = dataItem.value < 30;
case 'stress':
options.stroke = dataItem.value > 75;
case 'voice':
options.stroke = dataItem.state == 1 ? '#FF935A' : dataItem.state == 2 ? '#5A93FF' : null;
}
setProgress(dataItem.value, `progress-${dataItem.name}`, options);
break;
case 'seatbelt':
setSeatbelt(dataItem.value, dataItem.harness);
break;
case 'showHud':
document.getElementsByTagName('body')[0].style.opacity = dataItem.value ? 1 : 0;
break;
}
}
}
});
});

function setProgress(percent, className, options) {
let circle = document.getElementById(className);
if (circle === undefined) return;
if (percent !== undefined) {
Math.min(100, Math.max(0, percent));
let circumference = circle.r.baseVal.value * 2 * Math.PI;
//Why 0.81? i don't know, but it works
let offset = circumference - ((percent / 100) * 0.81) * circumference;

circle.style.strokeDasharray = circumference;
circle.style.strokeDashoffset = offset;
}
if (options !== undefined) {
for (var key in options) {
circle.style[key] = options[key] || null;
}
}
}

function setSeatbelt(toggle, harness) {
if (toggle === undefined) return;
document.getElementById('seatbelt').style.color = harness && '#5555aaff' || toggle && '#55aa55ff' || null;
}

function setSpeed(speed) {
if (typeof speed !== 'number') return;
speed = Math.round(speed);
document.getElementById('speed').innerHTML = speed;

if (speed > maxSpeedCounter) speed = maxSpeedCounter; // Can definitely happen with that random value returned by the native
setSpeedProgress(speed/maxSpeedCounter*100);
}

function setGauge(percentage, name, show) {
if (percentage === undefined) return;
let gauge = document.getElementById(name);
if (gauge === undefined) return;
if (show !== undefined) {
document.getElementById(name).style.opacity = show ? 1 : 0;
}
if (percentage > 100) percentage = 100;
let circle = document.getElementById('progress-' + name);
if (circle === undefined) return;
let circumference = circle.r.baseVal.value * 2 * Math.PI;
let offset = circumference - (percentage / 100 * 0.7) * circumference;

circle.style.strokeDasharray = `${circumference} ${circumference}`;
circle.style.strokeDashoffset = offset;

if (name === 'fuel') {
document.getElementById('progress-fuel').style.stroke = percentage > 30 ? '#ffffff' : percentage > 15 ? '#f39c12' : '#a40000';
}
}

/* thanks bing AI */
function setSpeedProgress(percentage) {
if (percentage === undefined) return;
if (percentage > 100) percentage = 100;
let circle = document.getElementById('progress-speed');
if (circle === undefined) return;
let circumference = circle.r.baseVal.value * 2 * Math.PI;
let offset = circumference - (percentage / 100 * 0.7) * circumference;

circle.style.strokeDasharray = `${circumference} ${circumference}`;
circle.style.strokeDashoffset = offset;
}

function setCompass(show, heading, street, zone) {
if (show) document.getElementsByClassName("compass-hud")[0].style.opacity = show ? 1 : 0;
if (heading) document.getElementById('azimuth').innerHTML = heading;
if (street) document.getElementById('street').innerHTML = street;
if (zone) document.getElementById('zone').innerHTML = zone;
}

function setDashboardLight(data) {
if (data.indicatorL !== undefined) {
if (data.indicatorL) {
document.getElementById('indicatorL').classList.add('indicator-active');
} else {
document.getElementById('indicatorL').classList.remove('indicator-active');
}
}
if (data.indicatorR !== undefined) {
if (data.indicatorR) {
document.getElementById('indicatorR').classList.add('indicator-active');
} else {
document.getElementById('indicatorR').classList.remove('indicator-active');
}
}
if (data.lowbeam !== undefined) {
document.getElementById('lowbeam').style.fill = data.lowbeam && '#0984e3' || '';
document.getElementById('lowbeam').style.opacity = data.lowbeam && '1.0' || '0.2';
if (data.lowbeam && !data.highbeam) {
data.highbeam = true;
}
}
if (data.highbeam !== undefined) {
document.getElementById('highbeam').style.fill = data.highbeam && '#2ecc71' || '';
document.getElementById('highbeam').style.opacity = data.highbeam && '1.0' || '0.2';
}
}
310 changes: 310 additions & 0 deletions html/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
@font-face {
font-family: 'Oxygen';
src: url("Oxygen-Regular.ttf");
}

@font-face {
font-family: 'Oxygen-Bold';
src: url(Oxygen-Bold.ttf);
}

@keyframes fadeLoop {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}

:root {
--player-hud-height: 20vh;
--player-hud-width: 3vw;
--player-hud-padding: 0.25em;
--progressradial-margin: 0.1em;
--progressradial-height: calc(var(--player-hud-height) / 4 - (2 * var(--progressradial-margin)));
--progressradial-width: calc(3vw - (2 * var(--player-hud-padding)));
--progressradial-circle-radius: calc((3vw - (2 * var(--player-hud-padding))) / 2 - 2px);
}

.player-hud {
position: absolute;
left: 16.5vw;
bottom: 0.5vh;
min-width: 50px;
width: var(--player-hud-width);
min-height: 100px;
height: var(--player-hud-height);
padding: var(--player-hud-padding);
box-sizing: border-box;
border-radius: 10px;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
}

.progressradial {
text-align: center;
margin-block: calc(var(--progressradial-margin) / 2);
height: var(--progressradial-height);
width: calc(3vw - (2 * var(--player-hud-padding)));
}

.progressradial svg {
margin-block: calc(var(--progressradial-margin) / 2);
height: var(--progressradial-height);
width: var(--progressradial-width);
}

.progressradial svg circle {
cx: 50%;
cy: 50%;
stroke-width: 0.225em;
r: 1.35em;
stroke: rgb(187, 200, 222);
stroke-opacity: 0.3;
}

#progress-voice {
stroke: #bbc8de;
stroke-opacity: 1;
}

.progress-icons {
font-size: 1.1em;
transform: translateY(-2em);
}

.player-hud .bars {
display: flex;
flex-direction: column;
justify-content: space-between;
min-width: 82.5%;
width: 100%;
height: 100%;
margin-left: 5px;
}

.player-hud .bars .type {
width: 97.5%;
height: min-content;
text-wrap: nowrap;
margin-block: 1px;
}

.player-hud .bars .type .icon {
display: inline-block;
vertical-align: middle;
margin-right: -4px;
text-align: center;
width: 20px;
}

.bars .type .progress {
display: inline-block;
vertical-align: middle;
margin-right: -4px;
margin-left: 8px;
width: calc(100% - 25px);
height: 0.75vh;
background-color: rgba(187, 200, 222, 0.3);
border-radius: 10px;
}

.bars .type .progress div {
display: block;
width: 10%;
height: 100%;
background-color: #bbc8de;
border-radius: 10px;
}

.fa-hamburger {
color: #dd6e14;
}

#progress-hunger {
stroke-opacity: 1;
stroke: #dd6e14;
}

.fa-tint {
color: #1a7cad;
}

#progress-thirst {
stroke-opacity: 1;
stroke: #1a7cad;
}

.fa-brain {
color: rgba(196, 0, 0);
}

#progress-stress {
stroke-opacity: 1;
stroke: rgba(196, 0, 0);
}

#progress-voice {
width: 0%;
}

i {
font-size: 1.25em;
color: #ffffff;
}

.fa-terminal {
color: #222222 !important;
}

.vehicle-hud {
position: absolute;
bottom: 0.5vh;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: row;
justify-content: space-between;
position: absolute;
width: fit-content;
height: 100px;
padding: 5px 5px 5px 5px;
box-sizing: border-box;
border-radius: 10px;
overflow: hidden;
align-items: center;
opacity: 0;
transition: opacity 0.5s linear;
}

.vehicle-hud .gauges {
display: flex;
flex-direction: row;
align-items: baseline;
font-family: Roboto, sans-serif;
font-weight: normal;
text-transform: uppercase;
}

#progress-speed {
stroke-dasharray: 219.911486 219.911486;
stroke-dashoffset: 219.911486;
}

#progress-fuel {
stroke-dasharray: 113.09733552923255 113.09733552923255 ;
stroke-dashoffset: 113.09733552923255 ;
stroke: white;
stroke-opacity: 0.8;
}

#progress-nitro {
stroke-dasharray: 113.09733552923255 113.09733552923255 ;
stroke-dashoffset: 113.09733552923255 ;
color: #1a7cad;
}

#speed {
fill: white;
font-size: 1.5em;
text-anchor: middle;
translate: 37.5px 37.5px;
}

#speed-unit {
font-size: 0.625em;
fill: rgba(255, 255, 255, 0.5);
text-anchor: middle;
translate: 37.5px 55px;
}

#fuel {
translate: -13px -15px;
}

#nitro {
margin-left: -15px;
translate: 12px -17px;
}

#seatbelt {
color: #aa5555ff;
margin-right: 5px;
}

.indicator {
fill: none;
stroke: white;
opacity: 0.2;
margin-inline: 5px;
}

.indicator-active {
stroke: #f39c12;
animation: fadeLoop 1s step-start infinite !important;
}

#highbeam {
fill: white;
opacity: 0.2;
margin-inline: 5px;
}

#lowbeam {
fill: white;
opacity: 0.2;
margin-inline: 5px;
}

.compass-hud {
font-family: 'Oxygen', sans-serif;
display: flex;
flex-direction: row;
align-items: center;
position: absolute;
bottom: 21vh;
left: 1.5vw;
opacity: 0;
transition: opacity 0.5s linear;
}

.compass-hud i {
font-size: 1.5em;
color: white;
margin-right: 5px;
}

#azimuth {
color: white;
font-size: 1.5em;
margin-right: 10px;
font-family: 'Oxygen-Bold', sans-serif;
}

.compass-hud .compass-location {
display: flex;
flex-direction: column;
justify-content: space-evenly;
font-size: 1.25em;
}

#street {
color: white;
}

.compass-hud .compass-location span {
height: 3px;
border-radius: 1px;
background-color: gray;
}

#zone {
color: rgb(150, 150, 150);
}
294 changes: 0 additions & 294 deletions html/styles.css

This file was deleted.

21 changes: 0 additions & 21 deletions locales/ar.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/cs.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/da.json

This file was deleted.

33 changes: 16 additions & 17 deletions locales/de.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
{
"notify": {
"hud_settings_loaded": "HUD Einstellungen geladen!",
"hud_restart": "HUD wird neugestartet!",
"hud_start": "HUD ist nun gestartet!",
"hud_command_info": "Dieser Befehl setzt deine jetzigen Einstellungen zurück!",
"load_square_map": "Quadratische Karte lädt..",
"loaded_square_map": "Quadratische Karte wurde geladen!",
"load_circle_map": "Kreiskarte lädt...",
"loaded_circle_map": "Kreiskarte wurde geladen!",
"cinematic_on": "Kino Modus aktiviert!",
"cinematic_off": "Kino Modus deaktiviert!",
"engine_on": "Motor ist nun an!",
"engine_off": "Motor ist nun aus!",
"low_fuel": "Tank Status niedrig!",
"access_denied": "Du bist nicht autorisiert!",
"stress_gain": "Stesslevel steigt!",
"stress_removed": "Du entspannst gerade!"
"low_fuel": "Kraftstoffstand niedrig!",
"stress_gain": "Fühl dich gestresster!",
"stress_removed": "Fühl dich entspannter!",
"cinematic_on": "Kinomodus aktiviert!",
"cinematic_off": "Kinomodus deaktiviert!",
"hud_on": "HUD aktiviert!",
"hud_off": "HUD deaktiviert!"
},
"commands": {
"bank": {
"help": "Zeige Bankguthaben"
},
"cash": {
"help": "Zeige Bargeldguthaben"
}
}
}
}
34 changes: 10 additions & 24 deletions locales/en.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,19 @@
{
"notify": {
"hud_settings_loaded": "HUD Settings Loaded!",
"hud_restart": "HUD Is Restarting!",
"hud_start": "HUD Is Now Started!",
"hud_command_info": "This command resets your current HUD settings!",
"load_square_map": "Square Map Loading...",
"loaded_square_map": "Square Map Has Loaded!",
"load_circle_map": "Circle Map Loading...",
"loaded_circle_map": "Circle Map Has Loaded!",
"cinematic_on": "Cinematic Mode On!",
"cinematic_off": "Cinematic Mode Off!",
"engine_on": "Engine Started!",
"engine_off": "Engine Shut Down!",
"low_fuel": "Fuel Level Low!",
"access_denied": "You Are Not Authorized!",
"stress_gain": "Feeling More Stressed!",
"stress_removed": "Feeling More Relaxed!"
},
"info": {
"open_menu": "Open Menu"
"stress_removed": "Feeling More Relaxed!",
"cinematic_on": "Cinematic Mode Enabled!",
"cinematic_off": "Cinematic Mode Disabled!",
"hud_on": "HUD Enabled!",
"hud_off": "HUD Disabled!"
},
"commands": {
"cash": "cash",
"bank": "bank",
"dev": "dev",
"help": {
"cash": "Check Cash Balance",
"bank": "Check Bank Balance",
"dev": "Enable/Disable developer Mode"
"bank": {
"help": "Show Bank Balance"
},
"cash": {
"help": "Show Cash Balance"
}
}
}
40 changes: 13 additions & 27 deletions locales/es.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,19 @@
{
"notify": {
"hud_settings_loaded": "Configuración de HUD cargada",
"hud_restart": "HUD reiniciando",
"hud_start": "HUD iniciado",
"hud_command_info": "Este comando reestablece la configuración del HUD",
"load_square_map": "Cargando mapa cuadrado...",
"loaded_square_map": "Mapa cuadrado cargado",
"load_circle_map": "Cargando mapa circular...",
"loaded_circle_map": "Mapa circular cargado",
"cinematic_on": "Modo cinematográfico activado",
"cinematic_off": "Modo cinematográfico desactivado",
"engine_on": "Motor encendido",
"engine_off": "Motor apagado",
"low_fuel": "Nivel de gasolina bajo",
"access_denied": "No estás autorizado para hacer eso",
"stress_gain": "Te estás sintiendo más estresado/a",
"stress_removed": "Te estás sintiendo más relajado/a"
},
"info": {
"open_menu": "Abrir Menú"
"low_fuel": "Nivel de combustible bajo!",
"stress_gain": "¡Te estresas!",
"stress_removed": "¡Te relajas!",
"cinematic_on": "¡Modo cinematográfico activado!",
"cinematic_off": "¡Modo cinematográfico desactivado!",
"hud_on": "¡HUD activado!",
"hud_off": "¡HUD desactivado!"
},
"commands": {
"cash": "efectivo",
"bank": "banco",
"dev": "dev",
"help": {
"cash": "Revisar balance en efectivo",
"bank": "Revisar balance en banco",
"dev": "Habilitar/deshabilitar modo desarrollador"
"bank": {
"help": "Mostrar saldo bancario"
},
"cash": {
"help": "Mostrar saldo en efectivo"
}
}
}
}
20 changes: 0 additions & 20 deletions locales/et.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/fa.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/fi.json

This file was deleted.

29 changes: 14 additions & 15 deletions locales/fr.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
{
"notify": {
"hud_settings_loaded": "Paramètres du HUD chargés!",
"hud_restart": "L'HUD redémarre!",
"hud_start": "L'HUD a demarré!",
"hud_command_info": "Cette commande réinitialise vos paramètre d'HUD!",
"load_square_map": "Chargement de la carte carrée...",
"loaded_square_map": "La carte carrée à chargée!",
"load_circle_map": "Chargement de la carte ronde...",
"loaded_circle_map": "La carte ronde à chargée!",
"low_fuel": "Niveau de carburant faible!",
"stress_gain": "Vous stressez!",
"stress_removed": "Vous vous détendez!",
"cinematic_on": "Mode cinématique activé!",
"cinematic_off": "Mode cinématique désactivé!",
"engine_on": "Moteur allumé!",
"engine_off": "Moteur éteint!",
"low_fuel": "Niveau d'essence bas!",
"access_denied": "Vous n'êtes pas autorisé!",
"stress_gain": "Vous stressez!",
"stress_removed": "Vous-vous relaxez!"
"hud_on": "HUD activé!",
"hud_off": "HUD désactivé!"
},
"commands": {
"bank": {
"help": "Afficher le solde bancaire"
},
"cash": {
"help": "Afficher le solde en espèces"
}
}
}
}
20 changes: 0 additions & 20 deletions locales/ge.json

This file was deleted.

33 changes: 16 additions & 17 deletions locales/it.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
{
"notify": {
"hud_settings_loaded": "Impostazioni HUD Caricate!",
"hud_restart": "L'HUD si sta restartando!",
"hud_start": "L'HUD si sta avviando!",
"hud_command_info": "Questo comando resetta le impostazioni dell'HUD!",
"load_square_map": "Caricando Mappa Quadrata...",
"loaded_square_map": "Mappa Quadrata Caricata!",
"load_circle_map": "Caricando Mappa Rotonda...",
"loaded_circle_map": "Mappa Rotonda Caricata!",
"cinematic_on": "Modalità Cinematica On!",
"cinematic_off": "Modalità Cinematica Off!",
"engine_on": "Motore Avviato!",
"engine_off": "Motore Spento!",
"low_fuel": "Livello Carburante Basso!",
"access_denied": "Non Sei Autorizzato!",
"stress_gain": "Ti Stai Stressando!",
"stress_removed": "Ti Stai Rilassando!"
"low_fuel": "Livello del carburante basso!",
"stress_gain": "Ti senti più stressato!",
"stress_removed": "Ti senti più rilassato!",
"cinematic_on": "Modalità cinematografica abilitata!",
"cinematic_off": "Modalità cinematografica disabilitata!",
"hud_on": "HUD abilitato!",
"hud_off": "HUD disabilitato!"
},
"commands": {
"bank": {
"help": "Mostra il saldo bancario"
},
"cash": {
"help": "Mostra il saldo in contanti"
}
}
}
}
20 changes: 0 additions & 20 deletions locales/nl.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/pl.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/pt.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/sk.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/sv.json

This file was deleted.

20 changes: 0 additions & 20 deletions locales/tr.json

This file was deleted.

86 changes: 2 additions & 84 deletions server/main.lua
Original file line number Diff line number Diff line change
@@ -1,91 +1,9 @@
local config = require 'config.server'
local sharedConfig = require 'config.shared'
local resetStress = false

-- Handlers
lib.versionCheck('Qbox-project/qbx_hud')

AddEventHandler('ox_inventory:openedInventory', function(source)
TriggerClientEvent('qbx_hud:client:hideHud', source)
end)

AddEventHandler('ox_inventory:closedInventory', function(source)
TriggerClientEvent('qbx_hud:client:showHud', source)
end)

-- Callbacks

lib.callback.register('hud:server:getMenu', function()
return sharedConfig.menu
end)

-- Network Events

RegisterNetEvent('hud:server:GainStress', function(amount)
local src = source
local player = exports.qbx_core:GetPlayer(src)
local newStress
if not player or (config.stress.disableForLEO and player.PlayerData.job.type == 'leo') then return end
if not resetStress then
if not player.PlayerData.metadata.stress then
player.PlayerData.metadata.stress = 0
end
newStress = player.PlayerData.metadata.stress + amount
if newStress <= 0 then newStress = 0 end
else
newStress = 0
end
if newStress > 100 then
newStress = 100
end
player.Functions.SetMetaData('stress', newStress)
TriggerClientEvent('hud:client:UpdateStress', src, newStress)
exports.qbx_core:Notify(src, locale('notify.stress_gain'), 'inform', 2500, nil, nil, {'#141517', '#ffffff'}, 'brain', '#C53030')
end)

RegisterNetEvent('hud:server:RelieveStress', function(amount)
local src = source
local player = exports.qbx_core:GetPlayer(src)
local newStress
if not player then return end
if not resetStress then
if not player.PlayerData.metadata.stress then
player.PlayerData.metadata.stress = 0
end
newStress = player.PlayerData.metadata.stress - amount
if newStress <= 0 then newStress = 0 end
else
newStress = 0
end
if newStress > 100 then
newStress = 100
end
player.Functions.SetMetaData('stress', newStress)
TriggerClientEvent('hud:client:UpdateStress', src, newStress)
exports.qbx_core:Notify(src, locale('notify.stress_removed'), 'inform', 2500, nil, nil, {'#141517', '#ffffff'}, 'brain', '#0F52BA')
end)

-- Commands

lib.addCommand(locale('commands.cash'), {
help = locale('commands.help.cash'),
restricted = 'group.admin'
}, function(source)
local player = exports.qbx_core:GetPlayer(source)
local cashAmount = player.PlayerData.money.cash
TriggerClientEvent('hud:client:ShowAccounts', source, 'cash', cashAmount)
end)

lib.addCommand(locale('commands.bank'), {
help = locale('commands.help.bank'),
}, function(source)
local player = exports.qbx_core:GetPlayer(source)
local bankAmount = player.PlayerData.money.bank
TriggerClientEvent('hud:client:ShowAccounts', source, 'bank', bankAmount)
end)

lib.addCommand('dev', {
help = locale('commands.help.dev'),
restricted = 'group.admin'
}, function(source)
TriggerClientEvent('qb-admin:client:ToggleDevmode', source)
end)
end)
26 changes: 26 additions & 0 deletions server/stress.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
local config = require 'config.server'

local function alterStress(source, amount)
local playerState = Player(source).state
local player = exports.qbx_core:GetPlayer(source)
if not player or (amount > 0 and config.disablePoliceStress and player.PlayerData.job.type == 'leo') then return end

local newStress = playerState.stress + amount
newStress = lib.math.clamp(newStress, 0, 100)

playerState:set("stress", newStress, true)

if amount > 0 then
exports.qbx_core:Notify(source, locale("notify.stress_gain"), 'inform', 2500, nil, nil, {'#141517', '#ffffff'}, 'brain', '#C53030')
else
exports.qbx_core:Notify(source, locale("notify.stress_removed"), 'inform', 2500, nil, nil, {'#141517', '#ffffff'}, 'brain', '#0F52BA')
end
end

RegisterNetEvent('hud:server:GainStress', function(amount)
alterStress(source, amount)
end)

RegisterNetEvent('hud:server:RelieveStress', function(amount)
alterStress(source, -amount)
end)
Binary file removed stream/circlemap.ytd
Binary file not shown.
Binary file removed stream/minimap.gfx
Binary file not shown.
Binary file removed stream/minimap.ytd
Binary file not shown.
Binary file removed stream/squaremap.ytd
Binary file not shown.