0.0.1
10
resources/[esx_addons]/esx_hud/.editorconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
max_line_length = 300
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
2
resources/[esx_addons]/esx_hud/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.vscode
|
||||
node_modules
|
||||
1
resources/[esx_addons]/esx_hud/.styluaignore
Normal file
@@ -0,0 +1 @@
|
||||
fxmanifest.lua
|
||||
50
resources/[esx_addons]/esx_hud/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
<h1 align='center'>[ESX] HUD</a></h1><p align='center'><b><a href='https://discord.esx-framework.org/'>Discord</a> - <a href='https://documentation.esx-framework.org/legacy/installation'>Documentation</a></b></h5>
|
||||
|
||||
We've brought you a clean, modern HUD that's easy to customise and configure. Integrated mileage calculation and more.
|
||||
|
||||
Features
|
||||
- Mileage calculation system
|
||||
- Indicator system with sound effect
|
||||
- Weapon HUD with ammo counter
|
||||
- Online player counter
|
||||
- Job label
|
||||
- Switch to mph or kmh
|
||||
- Color picker that allows you to customize the interface
|
||||
- Settings panel for additional settings
|
||||
- Different speedo layouts depending on vehicle type(LAND,AIR)
|
||||
- Seatbelt system with sound effect (Required script: esx_cruisecontrol)
|
||||
|
||||
## HUD UI
|
||||

|
||||
## SETTINGS UI
|
||||

|
||||
|
||||
## Developed by Gellipapa#9186 && Rav3n95#2849
|
||||
## Special thanks: Csoki, csontvazharcos, Füsti
|
||||
|
||||
## Download & Installation
|
||||
|
||||
- [Download Link](https://github.com/esx-framework/esx_hud/releases/latest/download/esx_hud.zip)
|
||||
- Put it in the `[addons]` directory
|
||||
- Open web folder in console and run these command `npm install` after `npm run build`
|
||||
- After that, the HUD will work correctly
|
||||
- Enjoy
|
||||
|
||||
## Installation
|
||||
- Add this to your `server.cfg`:
|
||||
|
||||
```
|
||||
ensure esx_hud
|
||||
```
|
||||
|
||||
# Legal
|
||||
### License
|
||||
esx_hud - hud script for ESX
|
||||
|
||||
Copyright (C) 2025 ESX-Framework
|
||||
|
||||
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
|
||||
|
||||
This program Is distributed In the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty Of MERCHANTABILITY Or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License For more details.
|
||||
|
||||
You should have received a copy Of the GNU General Public License along with this program. If Not, see http://www.gnu.org/licenses/.
|
||||
84
resources/[esx_addons]/esx_hud/client/commands.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
HUD.Data.hudHidden = false
|
||||
RegisterCommand("hud", function()
|
||||
HUD:Toggle(HUD.Data.hudHidden)
|
||||
HUD.Data.hudHidden = not HUD.Data.hudHidden
|
||||
end, false)
|
||||
|
||||
RegisterCommand("togglehud", function()
|
||||
HUD:Toggle(HUD.Data.hudHidden)
|
||||
HUD.Data.hudHidden = not HUD.Data.hudHidden
|
||||
end, false)
|
||||
|
||||
RegisterCommand("hudsettings", function()
|
||||
SendNUIMessage({ type = "OPEN_SETTINGS" })
|
||||
SetNuiFocus(true, true)
|
||||
end, false)
|
||||
|
||||
if not Config.Disable.VehicleHandlers and not Config.Disable.Vehicle then
|
||||
local leftSignal, rightSignal = false, false
|
||||
|
||||
ESX.RegisterInput("esx_hud:indicator:left", Translate("indicatorLeft"), "keyboard", "LEFT", function()
|
||||
if not HUD.Data.Vehicle then
|
||||
return
|
||||
end
|
||||
if HUD.Data.VehicleType == "AIR" then
|
||||
return
|
||||
end
|
||||
leftSignal = not leftSignal
|
||||
SetVehicleIndicatorLights(HUD.Data.Vehicle, 1, leftSignal)
|
||||
|
||||
local isAttached, trailer = GetVehicleTrailerVehicle(HUD.Data.Vehicle)
|
||||
if isAttached and DoesEntityExist(trailer) then
|
||||
SetVehicleIndicatorLights(trailer, 1, leftSignal)
|
||||
end
|
||||
end)
|
||||
|
||||
ESX.RegisterInput("esx_hud:indicator:right", Translate("indicatorRight"), "keyboard", "RIGHT", function()
|
||||
if not HUD.Data.Vehicle then
|
||||
return
|
||||
end
|
||||
if HUD.Data.VehicleType == "AIR" then
|
||||
return
|
||||
end
|
||||
rightSignal = not rightSignal
|
||||
SetVehicleIndicatorLights(HUD.Data.Vehicle, 0, rightSignal)
|
||||
|
||||
local isAttached, trailer = GetVehicleTrailerVehicle(HUD.Data.Vehicle)
|
||||
if isAttached and DoesEntityExist(trailer) then
|
||||
SetVehicleIndicatorLights(trailer, 0, rightSignal)
|
||||
end
|
||||
end)
|
||||
|
||||
ESX.RegisterInput("esx_hud:indicator:Hazard", Translate("indicatorHazard"), "keyboard", "UP", function()
|
||||
if not HUD.Data.Vehicle then
|
||||
return
|
||||
end
|
||||
if HUD.Data.VehicleType == "AIR" then
|
||||
return
|
||||
end
|
||||
if leftSignal ~= rightSignal then
|
||||
leftSignal = true
|
||||
rightSignal = true
|
||||
else
|
||||
leftSignal = not leftSignal
|
||||
rightSignal = not rightSignal
|
||||
end
|
||||
SetVehicleIndicatorLights(HUD.Data.Vehicle, 0, rightSignal)
|
||||
SetVehicleIndicatorLights(HUD.Data.Vehicle, 1, leftSignal)
|
||||
|
||||
local isAttached, trailer = GetVehicleTrailerVehicle(HUD.Data.Vehicle)
|
||||
if isAttached and DoesEntityExist(trailer) then
|
||||
SetVehicleIndicatorLights(trailer, 0, rightSignal)
|
||||
SetVehicleIndicatorLights(trailer, 1, leftSignal)
|
||||
end
|
||||
end)
|
||||
|
||||
ESX.RegisterInput("esx_hud:toggleEngine", Translate("toggleEngine"), "keyboard", "N", function()
|
||||
if not HUD.Data.Vehicle then
|
||||
return
|
||||
end
|
||||
local engineState = GetIsVehicleEngineRunning(HUD.Data.Vehicle)
|
||||
engineState = not engineState
|
||||
SetVehicleEngineOn(HUD.Data.Vehicle, engineState, false, true)
|
||||
end)
|
||||
end
|
||||
68
resources/[esx_addons]/esx_hud/client/main.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
function HUD:Toggle(state)
|
||||
SendNUIMessage({ type = "SHOW", value = state })
|
||||
end
|
||||
|
||||
function HUD:SetHudColor()
|
||||
SendNUIMessage({ type = "SET_CONFIG_DATA", value = Config })
|
||||
end
|
||||
|
||||
function HUD:Start(xPlayer)
|
||||
while not ESX.PlayerLoaded do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
if not xPlayer then
|
||||
xPlayer = ESX.GetPlayerData()
|
||||
end
|
||||
|
||||
self:SetHudColor()
|
||||
self:SlowThick()
|
||||
self:FastThick()
|
||||
|
||||
if not Config.Disable.Status then
|
||||
self:StatusThread()
|
||||
end
|
||||
|
||||
if not Config.Disable.Info then
|
||||
self:UpdateAccounts(xPlayer.accounts)
|
||||
end
|
||||
|
||||
if Config.Disable.MinimapOnFoot then
|
||||
DisplayRadar(false)
|
||||
end
|
||||
|
||||
self:Toggle(true)
|
||||
end
|
||||
|
||||
local function ToggleHud(state)
|
||||
HUD:Toggle(state)
|
||||
HUD.Data.hudHidden = not state
|
||||
end
|
||||
|
||||
RegisterNetEvent("esx_hud:HudToggle", ToggleHud)
|
||||
exports("HudToggle", ToggleHud)
|
||||
|
||||
-- Handlers
|
||||
-- On script start
|
||||
AddEventHandler("onResourceStart", function(resource)
|
||||
if GetCurrentResourceName() ~= resource then
|
||||
return
|
||||
end
|
||||
Wait(1000)
|
||||
HUD:Start()
|
||||
end)
|
||||
|
||||
-- On player loaded
|
||||
ESX.SecureNetEvent("esx:playerLoaded", function(xPlayer)
|
||||
while IsScreenFadedOut() do
|
||||
Wait(200)
|
||||
end
|
||||
|
||||
HUD:Start(xPlayer)
|
||||
end)
|
||||
|
||||
-- ForceLog or Logout
|
||||
ESX.SecureNetEvent("esx:onPlayerLogout", function()
|
||||
Wait(1000)
|
||||
HUD:Toggle(false)
|
||||
end)
|
||||
34
resources/[esx_addons]/esx_hud/client/nui.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
RegisterNUICallback("closePanel", function(data, cb)
|
||||
SetNuiFocus(false, false)
|
||||
cb("ok")
|
||||
end)
|
||||
|
||||
RegisterNUICallback("unitChanged", function(state, cb)
|
||||
if HUD.Data.Driver then
|
||||
if Config.Default.Kmh ~= state.unit then
|
||||
TriggerEvent("esx_hud:UnitChanged", state.unit)
|
||||
end
|
||||
end
|
||||
Config.Default.Kmh = state.unit
|
||||
cb("ok")
|
||||
end)
|
||||
|
||||
RegisterNUICallback("minimapSettingChanged", function(state, cb)
|
||||
Config.Disable.MinimapOnFoot = state.changed
|
||||
if IsPedOnFoot(ESX.PlayerData.ped) ~= 1 then
|
||||
return cb("ok")
|
||||
end
|
||||
DisplayRadar(not state.changed)
|
||||
cb("ok")
|
||||
end)
|
||||
|
||||
RegisterNUICallback("notify", function(data, cb)
|
||||
local state = data.state
|
||||
if state.reset then
|
||||
ESX.ShowNotification(Translate("settingsResetSuccess", 5000, "info"))
|
||||
cb("ok")
|
||||
return
|
||||
end
|
||||
ESX.ShowNotification(Translate("settingsSaveSuccess", 5000, "info"))
|
||||
cb("ok")
|
||||
end)
|
||||
164
resources/[esx_addons]/esx_hud/client/player/main.lua
Normal file
@@ -0,0 +1,164 @@
|
||||
local bool, ammoInClip = false, 0
|
||||
local WeaponList = {}
|
||||
function HUD:GetJobLabel()
|
||||
if not ESX.PlayerData.job then
|
||||
return
|
||||
end
|
||||
|
||||
if ESX.PlayerData.job.name == "unemployed" then
|
||||
return ESX.PlayerData.job.label
|
||||
end
|
||||
|
||||
local dutySuffix = ESX.PlayerData.job.onDuty and "" or Translate("job_off_duty")
|
||||
return string.format("%s - %s %s", ESX.PlayerData.job.label, ESX.PlayerData.job.grade_label, dutySuffix)
|
||||
end
|
||||
function HUD:GetLocation()
|
||||
local PPos = GetEntityCoords(ESX.PlayerData.ped)
|
||||
local streetHash = GetStreetNameAtCoord(PPos.x, PPos.y, PPos.z)
|
||||
local streetName = GetStreetNameFromHashKey(streetHash)
|
||||
return streetName
|
||||
end
|
||||
|
||||
function HUD:UpdateAccounts(accounts)
|
||||
if not Config.Disable.Money then
|
||||
if accounts == nil then
|
||||
return
|
||||
end
|
||||
for _, data in pairs(accounts) do
|
||||
if data.name == "bank" then
|
||||
self.Data.Money.bank = data.money
|
||||
elseif data.name == "money" then
|
||||
self.Data.Money.cash = data.money
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function HUD:GetWeapons()
|
||||
WeaponList = ESX.GetWeaponList(true)
|
||||
end
|
||||
|
||||
function HUD:SlowThick()
|
||||
CreateThread(function()
|
||||
while not ESX.PlayerLoaded do
|
||||
Wait(200)
|
||||
end
|
||||
while ESX.PlayerLoaded do
|
||||
self.Data.Position = GetEntityCoords(ESX.PlayerData.ped)
|
||||
|
||||
if not Config.Disable.Position then
|
||||
self.Data.Location = self:GetLocation()
|
||||
end
|
||||
|
||||
if not Config.Disable.Weapon then
|
||||
self.Data.Weapon.Active, self.Data.Weapon.CurrentWeapon = GetCurrentPedWeapon(ESX.PlayerData.ped, false)
|
||||
if self.Data.Weapon.CurrentWeapon == 0 then
|
||||
self.Data.Weapon.Active = false
|
||||
end
|
||||
if self.Data.Weapon.Active and WeaponList[self.Data.Weapon.CurrentWeapon] then
|
||||
self.Data.Weapon.MaxAmmo = (GetAmmoInPedWeapon(ESX.PlayerData.ped, self.Data.Weapon.CurrentWeapon) - ammoInClip)
|
||||
self.Data.Weapon.Name = WeaponList[self.Data.Weapon.CurrentWeapon].label and WeaponList[self.Data.Weapon.CurrentWeapon].label or false
|
||||
self.Data.Weapon.isWeaponMelee = not WeaponList[self.Data.Weapon.CurrentWeapon].ammo
|
||||
self.Data.Weapon.Image = string.gsub(WeaponList[self.Data.Weapon.CurrentWeapon].name, "WEAPON_", "")
|
||||
self.Data.Weapon.Image = string.lower(self.Data.Weapon.Image)
|
||||
end
|
||||
|
||||
--here we handle it when we find a hash that is not in the weapon list so we don't show the weapon data on the hud
|
||||
if self.Data.Weapon.Active then
|
||||
self.Data.Weapon.Active = self.Data.Weapon.CurrentWeapon ~= 0 and self.Data.Weapon.Name and self.Data.Weapon.Image
|
||||
end
|
||||
end
|
||||
|
||||
Wait(1000)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function HUD:FastThick()
|
||||
CreateThread(function()
|
||||
while not ESX.PlayerLoaded do
|
||||
Wait(200)
|
||||
end
|
||||
|
||||
local srvLogo = Config.Default.ServerLogo
|
||||
while ESX.PlayerLoaded do
|
||||
if not Config.Disable.Voice then
|
||||
self.Data.isTalking = NetworkIsPlayerTalking(ESX.playerId)
|
||||
end
|
||||
|
||||
if self.Data.Weapon.Active then
|
||||
bool, ammoInClip = GetAmmoInClip(ESX.PlayerData.ped, self.Data.Weapon.CurrentWeapon)
|
||||
self.Data.Weapon.CurrentAmmo = ammoInClip
|
||||
end
|
||||
|
||||
local values = {
|
||||
playerId = ESX.serverId,
|
||||
onlinePlayers = GlobalState["playerCount"],
|
||||
serverLogo = srvLogo,
|
||||
moneys = { bank = self.Data.Money.bank or 0, money = self.Data.Money.cash or 0 },
|
||||
weaponData = {
|
||||
use = self.Data.Weapon.Active,
|
||||
image = self.Data.Weapon.Image or false,
|
||||
name = self.Data.Weapon.Name or false,
|
||||
isWeaponMelee = self.Data.Weapon.isWeaponMelee,
|
||||
currentAmmo = self.Data.Weapon.CurrentAmmo or 0,
|
||||
maxAmmo = self.Data.Weapon.MaxAmmo or 0,
|
||||
},
|
||||
streetName = self.Data.Location or "Unknown street",
|
||||
voice = {
|
||||
mic = self.Data.isTalking or false,
|
||||
radio = self.Data.isTalkingOnRadio,
|
||||
range = self.Data.VoiceRange,
|
||||
},
|
||||
job = HUD:GetJobLabel(),
|
||||
}
|
||||
|
||||
SendNUIMessage({ type = "HUD_DATA", value = values })
|
||||
Wait(500)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Handlers
|
||||
-- On script start
|
||||
AddEventHandler("onResourceStart", function(resource)
|
||||
if GetCurrentResourceName() ~= resource then
|
||||
return
|
||||
end
|
||||
Wait(1000)
|
||||
if not Config.Disable.Weapon then
|
||||
HUD:GetWeapons()
|
||||
end
|
||||
end)
|
||||
|
||||
-- On player loaded
|
||||
ESX.SecureNetEvent("esx:playerLoaded", function(xPlayer)
|
||||
if not Config.Disable.Weapon then
|
||||
HUD:GetWeapons()
|
||||
end
|
||||
HUD:GetJobLabel(xPlayer.job)
|
||||
end)
|
||||
|
||||
AddEventHandler("esx:pauseMenuActive", function(state)
|
||||
if HUD.Data.hudHidden then
|
||||
return
|
||||
end
|
||||
HUD:Toggle(not state)
|
||||
end)
|
||||
|
||||
-- job handler
|
||||
RegisterNetEvent("esx:setJob")
|
||||
AddEventHandler("esx:setJob", function(job)
|
||||
ESX.PlayerData.job = job
|
||||
end)
|
||||
|
||||
--Cash and Bank handler
|
||||
if not Config.Disable.Money then
|
||||
RegisterNetEvent("esx:setAccountMoney", function(account)
|
||||
if account.name == "money" then
|
||||
HUD.Data.Money.cash = account.money
|
||||
elseif account.name == "bank" then
|
||||
HUD.Data.Money.bank = account.money
|
||||
end
|
||||
end)
|
||||
end
|
||||
52
resources/[esx_addons]/esx_hud/client/player/status.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
if not Config.Disable.Status then
|
||||
local GetPlayerUnderwaterTimeRemaining = GetPlayerUnderwaterTimeRemaining
|
||||
local GetPlayerSprintStaminaRemaining = GetPlayerSprintStaminaRemaining
|
||||
local IsPedSwimmingUnderWater = IsPedSwimmingUnderWater
|
||||
local GetEntityHealth = GetEntityHealth
|
||||
local GetEntityMaxHealth = GetEntityMaxHealth
|
||||
local GetPedArmour = GetPedArmour
|
||||
local values = {}
|
||||
|
||||
AddEventHandler("esx_status:onTick", function(data)
|
||||
local hunger, thirst
|
||||
for i = 1, #data do
|
||||
if data[i].name == "thirst" then
|
||||
thirst = math.floor(data[i].percent)
|
||||
end
|
||||
if data[i].name == "hunger" then
|
||||
hunger = math.floor(data[i].percent)
|
||||
end
|
||||
end
|
||||
|
||||
values.healthBar = math.floor((GetEntityHealth(ESX.PlayerData.ped) - 100) / 100 * 100)
|
||||
values.armorBar = GetPedArmour(ESX.PlayerData.ped)
|
||||
values.drinkBar = thirst
|
||||
values.foodBar = hunger
|
||||
end)
|
||||
|
||||
function HUD:StatusThread()
|
||||
values = {}
|
||||
CreateThread(function()
|
||||
while ESX.PlayerLoaded do
|
||||
local oxygen, stamina = 0, 0
|
||||
|
||||
stamina = math.floor(100 - GetPlayerSprintStaminaRemaining(ESX.playerId))
|
||||
if stamina == 0 then
|
||||
stamina = 1
|
||||
end
|
||||
if stamina == 100 then
|
||||
stamina = 0
|
||||
end
|
||||
|
||||
if IsPedSwimmingUnderWater(ESX.PlayerData.ped) then
|
||||
oxygen = math.floor(GetPlayerUnderwaterTimeRemaining(ESX.playerId) * 10)
|
||||
end
|
||||
|
||||
values.oxygenBar = oxygen or 0
|
||||
values.staminaBar = stamina
|
||||
SendNUIMessage({ type = "STATUS_HUD", value = values })
|
||||
Wait(250)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
11
resources/[esx_addons]/esx_hud/client/vehicle/fuel.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
if not Config.Disable.Vehicle then
|
||||
if GetResourceState("LegacyFuel") == "started" then
|
||||
function HUD:FuelExport()
|
||||
return ESX.Math.Round(exports["LegacyFuel"]:GetFuel(HUD.Data.Vehicle), 2)
|
||||
end
|
||||
else
|
||||
function HUD:FuelExport()
|
||||
return ESX.Math.Round(GetVehicleFuelLevel(HUD.Data.Vehicle), 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
190
resources/[esx_addons]/esx_hud/client/vehicle/main.lua
Normal file
@@ -0,0 +1,190 @@
|
||||
local cruiseControlStatus = false
|
||||
local isPassenger = false
|
||||
local isSeatbeltOn = false
|
||||
local p = promise:new()
|
||||
|
||||
local function SetCruiseControlState(state)
|
||||
cruiseControlStatus = state
|
||||
end
|
||||
|
||||
local function SetSeatbeltState(state)
|
||||
isSeatbeltOn = state
|
||||
end
|
||||
|
||||
exports("CruiseControlState", SetCruiseControlState)
|
||||
exports("SeatbeltState", SetSeatbeltState)
|
||||
|
||||
if not Config.Disable.Vehicle then
|
||||
local vehicleType, playerPos
|
||||
local currentMileage = 0
|
||||
|
||||
HUD.Data.Driver = false
|
||||
|
||||
local values = {
|
||||
show = false,
|
||||
defaultIndicators = {},
|
||||
}
|
||||
|
||||
local function driverCheck(currentVehicle)
|
||||
return DoesEntityExist(currentVehicle) and (GetPedInVehicleSeat(currentVehicle, -1) == ESX.PlayerData.ped)
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local currentVehicle = Citizen.Await(p)
|
||||
if currentVehicle then
|
||||
HUD.Data.Driver = driverCheck(currentVehicle)
|
||||
playerPos = GetEntityCoords(ESX.PlayerData.ped).xy
|
||||
|
||||
if not Config.Default.PassengerSpeedo then
|
||||
if HUD.Data.Driver then
|
||||
isPassenger = false
|
||||
else
|
||||
SendNUIMessage({ type = "VEH_HUD", value = { show = false } })
|
||||
isPassenger = true
|
||||
end
|
||||
end
|
||||
end
|
||||
Wait(1000)
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
local oldPos
|
||||
while true do
|
||||
local currentVehicle = Citizen.Await(p)
|
||||
if currentVehicle and DoesEntityExist(currentVehicle) then
|
||||
local engineHealth = math.floor(GetVehicleEngineHealth(currentVehicle) / 10)
|
||||
local _, lowBeam, highBeam = GetVehicleLightsState(currentVehicle)
|
||||
local indicator = GetVehicleIndicatorLights(currentVehicle)
|
||||
local tempDoorLockStatus = GetVehicleDoorLockStatus(currentVehicle)
|
||||
|
||||
if engineHealth < 0 then
|
||||
engineHealth = 0
|
||||
end
|
||||
|
||||
local lightState = lowBeam == 1 or highBeam == 1
|
||||
local indicatorLeft = indicator == 1 or indicator == 3
|
||||
local indicatorRight = indicator == 2 or indicator == 3
|
||||
local doorLockStatus = tempDoorLockStatus == 2 or tempDoorLockStatus == 3
|
||||
|
||||
if IsVehicleOnAllWheels(currentVehicle) then
|
||||
if oldPos then
|
||||
local distance = #(oldPos - playerPos)
|
||||
if distance >= 10 then
|
||||
currentMileage += Config.Default.Kmh and distance / 1000 or distance / 1620
|
||||
currentMileage = ESX.Math.Round(currentMileage, 2)
|
||||
oldPos = playerPos
|
||||
end
|
||||
else
|
||||
oldPos = playerPos
|
||||
end
|
||||
end
|
||||
|
||||
values.fuel = { level = HUD:FuelExport() or 100, maxLevel = 100 }
|
||||
values.mileage = currentMileage
|
||||
values.kmh = Config.Default.Kmh
|
||||
values.damage = engineHealth
|
||||
values.vehType = vehicleType
|
||||
values.driver = HUD.Data.Driver
|
||||
values.defaultIndicators.seatbelt = isSeatbeltOn
|
||||
values.defaultIndicators.tempomat = cruiseControlStatus
|
||||
values.defaultIndicators.door = doorLockStatus
|
||||
values.defaultIndicators.light = lightState
|
||||
values.defaultIndicators.leftIndex = indicatorLeft
|
||||
values.defaultIndicators.rightIndex = indicatorRight
|
||||
end
|
||||
Wait(200)
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local currentVehicle = Citizen.Await(p)
|
||||
if currentVehicle and DoesEntityExist(currentVehicle) then
|
||||
local currentSpeed = GetEntitySpeed(currentVehicle)
|
||||
local engineRunning = GetIsVehicleEngineRunning(currentVehicle)
|
||||
local rpm
|
||||
|
||||
if vehicleType == "LAND" or vehicleType == "MOTO" then
|
||||
rpm = engineRunning and (GetVehicleCurrentRpm(currentVehicle) * 450) or 0
|
||||
else
|
||||
rpm = math.ceil(ESX.PlayerData.coords.z)
|
||||
end
|
||||
|
||||
values.speed = math.floor(currentSpeed * (Config.Default.Kmh and 3.6 or 2.236936))
|
||||
values.rpm = rpm
|
||||
values.defaultIndicators.engine = engineRunning
|
||||
|
||||
if not isPassenger then
|
||||
SendNUIMessage({ type = "VEH_HUD", value = values })
|
||||
end
|
||||
end
|
||||
Wait(50)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("esx:enteredVehicle", function(currentVehicle, currentPlate, currentSeat, displayName, netId)
|
||||
local vehicleClass = GetVehicleClass(currentVehicle)
|
||||
if vehicleClass == 13 then
|
||||
return
|
||||
end
|
||||
|
||||
HUD.Data.Driver = currentSeat == -1 or false
|
||||
HUD.Data.Vehicle = currentVehicle
|
||||
vehicleType = "LAND"
|
||||
|
||||
if vehicleClass == 15 or vehicleClass == 16 then
|
||||
vehicleType = "AIR"
|
||||
elseif vehicleClass == 8 then
|
||||
vehicleType = "MOTO"
|
||||
end
|
||||
|
||||
if Config.Disable.MinimapOnFoot then
|
||||
DisplayRadar(true)
|
||||
end
|
||||
|
||||
if HUD.Data.Driver then
|
||||
TriggerServerEvent("esx_hud:EnteredVehicle", currentPlate, Config.Default.Kmh)
|
||||
end
|
||||
values.show = true
|
||||
p:resolve(currentVehicle)
|
||||
end)
|
||||
|
||||
AddEventHandler("esx:exitedVehicle", function(currentVehicle, currentPlate, currentSeat, displayName, netId)
|
||||
p = promise:new()
|
||||
HUD.Data.Driver = false
|
||||
HUD.Data.Vehicle = nil
|
||||
vehicleType = nil
|
||||
|
||||
values = {
|
||||
show = false,
|
||||
defaultIndicators = {},
|
||||
}
|
||||
|
||||
SendNUIMessage({ type = "VEH_HUD", value = { show = false } })
|
||||
|
||||
if Config.Disable.MinimapOnFoot then
|
||||
DisplayRadar(false)
|
||||
end
|
||||
|
||||
if currentSeat == -1 then
|
||||
TriggerServerEvent("esx_hud:ExitedVehicle", currentPlate, currentMileage, Config.Default.Kmh)
|
||||
end
|
||||
currentMileage = 0
|
||||
isPassenger = false
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx_hud:UpdateMileage", function(mileage)
|
||||
currentMileage = mileage
|
||||
end)
|
||||
|
||||
AddEventHandler("esx_hud:UnitChanged", function(state)
|
||||
if state then
|
||||
currentMileage = currentMileage * 1.61
|
||||
else
|
||||
currentMileage = currentMileage / 1.61
|
||||
end
|
||||
currentMileage = ESX.Math.Round(currentMileage, 2)
|
||||
end)
|
||||
end
|
||||
33
resources/[esx_addons]/esx_hud/client/voice.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
if not Config.Disable.Voice then
|
||||
HUD.Data.TalkingOnRadio = false
|
||||
if GetResourceState("pma-voice") == "started" then
|
||||
AddEventHandler("pma-voice:setTalkingMode", function(mode)
|
||||
SendNUIMessage({ type = "VOICE_RANGE", value = mode })
|
||||
HUD.Data.VoiceRange = mode
|
||||
end)
|
||||
|
||||
AddEventHandler("pma-voice:radioActive", function(radioTalking)
|
||||
HUD.Data.isTalkingOnRadio = radioTalking
|
||||
end)
|
||||
|
||||
AddEventHandler("onResourceStart", function(resourceName)
|
||||
if not resourceName == "pma-voice" then
|
||||
return
|
||||
end
|
||||
Wait(1000)
|
||||
SendNUIMessage({ type = "VOICE_RANGE", value = LocalPlayer.state.proximity.index })
|
||||
end)
|
||||
elseif GetResourceState("saltychat") == "started" then
|
||||
-- #TODO: Test salty chat, add restart handlers
|
||||
AddEventHandler("SaltyChat_VoiceRangeChanged", function(range, index, availableVoiceRanges)
|
||||
SendNUIMessage({ type = "VOICE_RANGE", value = index })
|
||||
HUD.Data.VoiceRange = index
|
||||
end)
|
||||
|
||||
AddEventHandler("SaltyChat_RadioTrafficStateChanged", function(primaryReceive, primaryTransmit, secondaryReceive, secondaryTransmit)
|
||||
HUD.Data.isTalkingOnRadio = primaryTransmit or secondaryTransmit
|
||||
end)
|
||||
else
|
||||
TriggerServerEvent("esx_hud:ErrorHandle", "Setup your custom voice resource at: client/voice.lua")
|
||||
end
|
||||
end
|
||||
39
resources/[esx_addons]/esx_hud/fxmanifest.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
fx_version "cerulean"
|
||||
game "gta5"
|
||||
lua54 "yes"
|
||||
|
||||
description "The default HUD resource for ESX-Legacy."
|
||||
version "1.10.2"
|
||||
legacyversion '1.13.4'
|
||||
|
||||
shared_scripts {
|
||||
"@es_extended/imports.lua",
|
||||
"@es_extended/locale.lua",
|
||||
"shared/config.lua",
|
||||
"shared/main.lua",
|
||||
"locales/*.lua",
|
||||
}
|
||||
|
||||
server_scripts {
|
||||
"@oxmysql/lib/MySQL.lua",
|
||||
"server/*.lua",
|
||||
}
|
||||
|
||||
client_scripts {
|
||||
"client/*.lua",
|
||||
"client/player/*.lua",
|
||||
"client/vehicle/*.lua",
|
||||
}
|
||||
|
||||
ui_page "web/dist/index.html"
|
||||
|
||||
files {
|
||||
"web/dist/**",
|
||||
"web/dist/assets/**",
|
||||
}
|
||||
|
||||
dependencies {
|
||||
"es_extended",
|
||||
"esx_status",
|
||||
"oxmysql",
|
||||
}
|
||||
BIN
resources/[esx_addons]/esx_hud/img.png
Normal file
|
After Width: | Height: | Size: 4.2 MiB |
BIN
resources/[esx_addons]/esx_hud/img_1.png
Normal file
|
After Width: | Height: | Size: 3.5 MiB |
16
resources/[esx_addons]/esx_hud/locales/da.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["da"] = {
|
||||
toggleHud = "Slå HUD til/fra",
|
||||
indicatorLeft = "Venstre indikator",
|
||||
indicatorRight = "Højre indikator",
|
||||
toggleEngine = "Motor tænd/sluk",
|
||||
speedChanged = "Fart ændret, ny hastighed: ",
|
||||
resource_not_built = "Ressourcen er ikke lavet, download venligst udgivelsesversionen",
|
||||
settingsSaveSuccess = "De nuværende indstillinger er gemt",
|
||||
settingsResetSuccess = "Indstillingerne blev nulstillet",
|
||||
currentVersion = "Seneste version: ",
|
||||
yourVersion = "Din version: ",
|
||||
latestVersion = "Du bruger den seneste version!",
|
||||
needUpdateResource = "Du skal downloade den nyeste version! Du bruger en gammel version i øjeblikket!",
|
||||
errorGetCurrentVersion = "Der opstod en fejl under forsøget på at hente den nuværende version!",
|
||||
job_off_duty = " (Ikke på vagt)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/de.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["de"] = {
|
||||
toggleHud = "HUD An / Ausschalten",
|
||||
indicatorLeft = "Linker Blinker",
|
||||
indicatorRight = "Rechter Blinker",
|
||||
toggleEngine = "Motor an / aus",
|
||||
speedChanged = "Geschwindigkeit geändert! Neue Geschwindigkeit: ",
|
||||
resource_not_built = "Resource ist gebuilded! Downloade die neuste version!",
|
||||
settingsSaveSuccess = "Erfolgreich die derzeitigen einstellungen gespeichert!",
|
||||
settingsResetSuccess = "Einstellungen erfolgreich zurückgesetzt",
|
||||
currentVersion = "Letzte Version: ",
|
||||
yourVersion = "Deine Version: ",
|
||||
latestVersion = "Du nutzt die neuste Version von esx_hud!",
|
||||
needUpdateResource = "Du musst die letze Version downloaden! Installiere die neuste Version!",
|
||||
errorGetCurrentVersion = "Ein Fehler kam als die Versionsabfrage durchgeführt wurde!",
|
||||
job_off_duty = " (Außer Dienst)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/en.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["en"] = {
|
||||
toggleHud = "Turn HUD on / off",
|
||||
indicatorLeft = "Left indicator",
|
||||
indicatorRight = "Right indicator",
|
||||
toggleEngine = "Engine on / off",
|
||||
speedChanged = "Speed changed, new speed: ",
|
||||
resource_not_built = "Resource are not built, please download the release version",
|
||||
settingsSaveSuccess = "Successfully save current settings",
|
||||
settingsResetSuccess = "Successfully reset settings",
|
||||
currentVersion = "Latest version: ",
|
||||
yourVersion = "Your version: ",
|
||||
latestVersion = "You are using the latest version!",
|
||||
needUpdateResource = "You need download latest version! You are using an old version at the moment!",
|
||||
errorGetCurrentVersion = "An error occurred while trying to get the current version!",
|
||||
job_off_duty = " (Off-Duty)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/fi.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["fi"] = {
|
||||
toggleHud = "HUD päälle / kiinni",
|
||||
indicatorLeft = "Vasen vilkku",
|
||||
indicatorRight = "Oikea vilkku",
|
||||
toggleEngine = "Moottori päälle / kiinni",
|
||||
speedChanged = "Nopeutta muutettu, uusi nopeus: ",
|
||||
resource_not_built = "Resursseja ei ole rakennettu, lataa julkaisuversio",
|
||||
settingsSaveSuccess = "Nykyisten asetusten tallentaminen onnistui",
|
||||
settingsResetSuccess = "Asetusten nollaus onnistui",
|
||||
currentVersion = "Uusin versio: ",
|
||||
yourVersion = "Sinun versio: ",
|
||||
latestVersion = "Käytät uusinta versiota!",
|
||||
needUpdateResource = "Sinun on ladattava uusin versio! Käytät tällä hetkellä vanhaa versiota!",
|
||||
errorGetCurrentVersion = "Virhe yritettäessä saada nykyinen versio!",
|
||||
job_off_duty = " (Vapaalla)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/fr.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["fr"] = {
|
||||
toggleHud = "Activer/Désactiver l'hud",
|
||||
indicatorLeft = "Clignotant gauche",
|
||||
indicatorRight = "Clignotant droit",
|
||||
toggleEngine = "Allumer/éteindre le moteur",
|
||||
speedChanged = "La vitesse a été changée, nouvelle vitesse: ",
|
||||
resource_not_built = "La ressource n'est pas build, télécharger une version officielle ou compilez la ressource vous même",
|
||||
settingsSaveSuccess = "Les paramètres actuels ont bien été sauvegardés",
|
||||
settingsResetSuccess = "Les paramètres ont bien été réinitialisés",
|
||||
currentVersion = "Dernière version: ",
|
||||
yourVersion = "Votre version: ",
|
||||
latestVersion = "Vous utilisez la dernière version!",
|
||||
needUpdateResource = "Vous devez télécharger la dernière version! Vous utilisez actuellement une ancienne version!",
|
||||
errorGetCurrentVersion = "Une erreur s'est produite lors de la tentative d'obtention de la version actuelle!",
|
||||
job_off_duty = " (Hors service)",
|
||||
}
|
||||
18
resources/[esx_addons]/esx_hud/locales/hu.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
Locales["hu"] = {
|
||||
toggleHud = "Hud ki / be kapcsolása",
|
||||
indicatorLeft = "Bal index",
|
||||
indicatorRight = "Jobb index",
|
||||
toggleEngine = "Motor ki / be kapcsolása",
|
||||
increaseSpeed = "(Tempomat) Sebbeség nővelése",
|
||||
decreaseSpeed = "(Tempomat) Sebbeség csökkenentése",
|
||||
speedChanged = "Sebesség megváltoztatva, új sebbeség: ",
|
||||
resource_not_built = "Nincs le buildelve a resource, kérlek töltsd le a release-t",
|
||||
settingsSaveSuccess = "Sikeresen megtörtént a mentése beállításoknak!",
|
||||
settingsResetSuccess = "Sikeresen megtörtént a visszaállítása a beállításoknak!",
|
||||
latestVersion = "Legújabb verziót használod!",
|
||||
currentVersion = "Legfrissebb verzió: ",
|
||||
yourVersion = "Jelenlegi verziód: ",
|
||||
needUpdateResource = "Elavult a verziód töltsd le a legújabbat!",
|
||||
errorGetCurrentVersion = "Hiba történt a verzió lekérdezés közben!",
|
||||
job_off_duty = " (Szabadnapos)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/it.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["it"] = {
|
||||
toggleHud = "Attiva / disattiva HUD",
|
||||
indicatorLeft = "Indicatore sinistro",
|
||||
indicatorRight = "Indicatore destro",
|
||||
toggleEngine = "Motore acceso/spento",
|
||||
speedChanged = "Velocità modificata, nuova velocità: ",
|
||||
resource_not_built = "La risorsa non è stata buildata, scarica la versione release, non il source code!",
|
||||
settingsSaveSuccess = "Salvataggio delle impostazioni correnti riuscito",
|
||||
settingsResetSuccess = "Ripristino impostazioni riuscito",
|
||||
currentVersion = "Ultima versione ",
|
||||
yourVersion = "La tua versione:",
|
||||
latestVersion = "Stai utilizzando l'ultima versione!",
|
||||
needUpdateResource = "Devi scaricare l'ultima versione! Al momento stai usando una vecchia versione!",
|
||||
errorGetCurrentVersion = "Si è verificato un errore durante il tentativo di ottenere la versione corrente!",
|
||||
job_off_duty = " (Fuori servizio)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/nl.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["nl"] = {
|
||||
toggleHud = "Zet HUD aan / uit",
|
||||
indicatorLeft = "Linker richtingaanwijzer",
|
||||
indicatorRight = "Rechter richtingaanwijzer",
|
||||
toggleEngine = "Motor aan / uit",
|
||||
speedChanged = "Snelheid veranderd, nieuwe snelheid: ",
|
||||
resource_not_built = "Resource is niet gebouwd, download de releaseversie",
|
||||
settingsSaveSuccess = "De instellingen zijn succesvol opgeslagen",
|
||||
settingsResetSuccess = "De instellingen zijn succesvol gereset",
|
||||
currentVersion = "Laatste versie: ",
|
||||
yourVersion = "Jouw versie: ",
|
||||
latestVersion = "Je gebruikt de laatste versie !",
|
||||
needUpdateResource = "Je bent een oude versie aan het gebruiken ! download de nieuwste versie !",
|
||||
errorGetCurrentVersion = "Er is een error ontstaan tijdens het ophalen van de huidige versie !",
|
||||
job_off_duty = " (Niet in dienst)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/pt.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["pt"] = {
|
||||
toggleHud = "Ligar o HUD, on / off",
|
||||
indicatorLeft = "Pisca esquerdo",
|
||||
indicatorRight = "Pisca direito",
|
||||
toggleEngine = "Motor, on / off",
|
||||
speedChanged = "Velocidade alterada, nova velocidade: ",
|
||||
resource_not_built = 'O resource não foi construido, por favor faz download da versão "Release"',
|
||||
settingsSaveSuccess = "Salvaste as atuais definições com sucesso",
|
||||
settingsResetSuccess = "Formataste as definições com sucesso",
|
||||
currentVersion = "Versão mais recente: ",
|
||||
yourVersion = "A tua versão: ",
|
||||
latestVersion = "Estás a usar a versão mais recente!",
|
||||
needUpdateResource = "Precisas de descarregar a versão mais recente! Neste momento, estás a utilizar uma versão antiga!",
|
||||
errorGetCurrentVersion = "Ocorreu um erro ao tentar obter a versão atual!",
|
||||
job_off_duty = " (Fora de serviço)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/sr.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["sr"] = {
|
||||
toggleHud = "Upalite/Ugasite HUD",
|
||||
indicatorLeft = "Levi migavac",
|
||||
indicatorRight = "Desni migavac",
|
||||
toggleEngine = "Motor upaljen/ugašen",
|
||||
speedChanged = "Brzina promenjena, nova brzina: ",
|
||||
resource_not_built = "Resurs nije napravljen, preuzmite release verziju resursa!",
|
||||
settingsSaveSuccess = "Trenutna podešavanja uspešno sačuvana",
|
||||
settingsResetSuccess = "Podešavanja uspešno resetovana",
|
||||
currentVersion = "Poslednja verzija: ",
|
||||
yourVersion = "Vaša verzija: ",
|
||||
latestVersion = "Vi koristite poslednju verziju!",
|
||||
needUpdateResource = "Morate preuzeti najnoviju verziju. Trenutno koristite staru verziju.",
|
||||
errorGetCurrentVersion = "Došlo je do greške prilikom provere trenutne verzije resursa!",
|
||||
job_off_duty = " (Van dužnosti)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/sv.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["sv"] = {
|
||||
toggleHud = "Sätt HUD på / av",
|
||||
indicatorLeft = "Vänster blinkers",
|
||||
indicatorRight = "Höger blinkers",
|
||||
toggleEngine = "Motor på / av",
|
||||
speedChanged = "Hastighet ändrad, ny hastighet: ",
|
||||
resource_not_built = "Resource är inte byggd, ladda ner release versionen",
|
||||
settingsSaveSuccess = "Inställningar sparade",
|
||||
settingsResetSuccess = "Inställningar återställda",
|
||||
currentVersion = "Senaste version: ",
|
||||
yourVersion = "Din version: ",
|
||||
latestVersion = "Du använder den senaste versionen!",
|
||||
needUpdateResource = "Du behöver ladda ner den senaste versionen! Du använder en gammal version just nu!",
|
||||
errorGetCurrentVersion = "Ett fel inträffade med att ladda ner den senaste versionen!",
|
||||
job_off_duty = " (Ledig)",
|
||||
}
|
||||
16
resources/[esx_addons]/esx_hud/locales/tr.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
Locales["tr"] = {
|
||||
toggleHud = "HUD'u aç / kapat",
|
||||
indicatorLeft = "Sol sinyal",
|
||||
indicatorRight = "Sağ sinyal",
|
||||
toggleEngine = "Motoru aç / kapat",
|
||||
speedChanged = "Hız değiştirildi, yeni hız: ",
|
||||
resource_not_built = "Kaynak kurulmamış, lütfen son sürümü indirin",
|
||||
settingsSaveSuccess = "Ayarlar başarıyla kaydedildi",
|
||||
settingsResetSuccess = "Ayarlar başarıyla sıfırlandı",
|
||||
currentVersion = "En son sürüm: ",
|
||||
yourVersion = "Sizin sürümünüz: ",
|
||||
latestVersion = "Şu anda en son sürümü kullanıyorsunuz!",
|
||||
needUpdateResource = "En son sürümü indirmeniz gerekiyor! Şu anda eski bir sürümü kullanıyorsunuz!",
|
||||
errorGetCurrentVersion = "Geçerli sürümü alırken bir hata oluştu!",
|
||||
job_off_duty = " (Görev dışı)",
|
||||
}
|
||||
95
resources/[esx_addons]/esx_hud/server/main.lua
Normal file
@@ -0,0 +1,95 @@
|
||||
HUD = HUD or {}
|
||||
|
||||
HUD.VersionCheckBaseURL = "https://raw.githubusercontent.com/esx-framework/ESX-Legacy-Addons/main/%5Besx_addons%5D/"
|
||||
|
||||
function HUD:ErrorHandle(msg)
|
||||
local resourceName = GetCurrentResourceName()
|
||||
print(("[^1ERROR^7] ^3%s^7: %s"):format(resourceName, msg))
|
||||
end
|
||||
|
||||
function HUD:InfoHandle(msg, color)
|
||||
local resourceName = GetCurrentResourceName()
|
||||
local c = ({green=2, red=1, blue=4})[color] or 3
|
||||
print(("[^9INFO^7] ^3%s^7: ^" .. c .. "%s^7"):format(resourceName, msg))
|
||||
end
|
||||
|
||||
local function normalizeSemver(v)
|
||||
if type(v) ~= "string" then return nil end
|
||||
local three = v:match("%d+%.%d+%.%d+")
|
||||
if three then return three end
|
||||
local two = v:match("^%d+%.%d+$")
|
||||
if two then return (two .. ".0") end
|
||||
local one = v:match("^%d+$")
|
||||
if one then return (one .. ".0.0") end
|
||||
return nil
|
||||
end
|
||||
|
||||
VERSION = {
|
||||
Check = function(err, response, headers)
|
||||
local resourceName = GetCurrentResourceName()
|
||||
local currentVersion = GetResourceMetadata(resourceName, "version", 0)
|
||||
if not currentVersion then return end
|
||||
|
||||
local manifestURL = HUD.VersionCheckBaseURL .. resourceName .. "/fxmanifest.lua"
|
||||
HUD:InfoHandle(("Checking manifest from %s"):format(manifestURL), "blue")
|
||||
|
||||
if err ~= 200 or not response then
|
||||
HUD:ErrorHandle(Translate("errorGetCurrentVersion"))
|
||||
return
|
||||
end
|
||||
|
||||
local remoteVersion = response:match("version%s+'([%d%.]+)'")
|
||||
if not remoteVersion then
|
||||
HUD:ErrorHandle(Translate("errorGetRemoteVersion"))
|
||||
return
|
||||
end
|
||||
|
||||
local latestVersion = normalizeSemver(remoteVersion)
|
||||
currentVersion = normalizeSemver(currentVersion)
|
||||
|
||||
if not latestVersion or not currentVersion then
|
||||
HUD:ErrorHandle(Translate("invalidVersion"))
|
||||
return
|
||||
end
|
||||
|
||||
if currentVersion == latestVersion then
|
||||
HUD:InfoHandle(Translate("latestVersion"), "green")
|
||||
HUD:InfoHandle(("Up to date version (%s)"):format(currentVersion), "green")
|
||||
return
|
||||
end
|
||||
|
||||
local currentVersionSplitted = { string.strsplit(".", currentVersion) }
|
||||
local latestVersionSplitted = { string.strsplit(".", latestVersion) }
|
||||
|
||||
HUD:InfoHandle(Translate("currentVersion") .. latestVersion, "green")
|
||||
HUD:InfoHandle(Translate("yourVersion") .. currentVersion, "blue")
|
||||
HUD:InfoHandle(("Update available: remote %s > local %s"):format(latestVersion, currentVersion), "red")
|
||||
|
||||
for i = 1, #currentVersionSplitted do
|
||||
local current, latest = tonumber(currentVersionSplitted[i]), tonumber(latestVersionSplitted[i])
|
||||
if current ~= latest then
|
||||
if not current or not latest then return end
|
||||
if current < latest then
|
||||
HUD:InfoHandle(Translate("needUpdateResource"), "red")
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
RunVersionChecker = function()
|
||||
CreateThread(function()
|
||||
local resourceName = GetCurrentResourceName()
|
||||
local manifestURL = HUD.VersionCheckBaseURL .. resourceName .. "/fxmanifest.lua"
|
||||
PerformHttpRequest(manifestURL, VERSION.Check, "GET")
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
AddEventHandler("onResourceStart", function(resourceName)
|
||||
local currentName = GetCurrentResourceName()
|
||||
if resourceName ~= currentName then return end
|
||||
|
||||
Wait(100)
|
||||
VERSION:RunVersionChecker()
|
||||
end)
|
||||
123
resources/[esx_addons]/esx_hud/server/mileage.lua
Normal file
@@ -0,0 +1,123 @@
|
||||
if not Config.Disable.Vehicle then
|
||||
HUD.Mileage = {
|
||||
Data = {},
|
||||
}
|
||||
|
||||
local Mileage = HUD.Mileage
|
||||
|
||||
-- Create column in sql if not exist
|
||||
-- CREDIT: Overextended (https://github.com/overextended)
|
||||
CreateThread(function()
|
||||
local success, result = pcall(MySQL.query.await, "SELECT mileage FROM owned_vehicles")
|
||||
if not success then
|
||||
MySQL.query("ALTER TABLE owned_vehicles ADD COLUMN `mileage` FLOAT(10) DEFAULT 0; ")
|
||||
end
|
||||
end)
|
||||
|
||||
function Mileage:Load(plate, playerId, kmh)
|
||||
MySQL.single("SELECT mileage FROM owned_vehicles WHERE plate = ?", { plate }, function(data)
|
||||
local mileage, owned
|
||||
if data then
|
||||
mileage, owned = data.mileage, true
|
||||
if kmh then
|
||||
mileage = mileage * 1.61
|
||||
end
|
||||
else
|
||||
mileage, owned = math.random(100, 10000), false
|
||||
end
|
||||
self:Create(plate, mileage, owned, playerId)
|
||||
end)
|
||||
end
|
||||
|
||||
function Mileage:Save()
|
||||
if next(Mileage.Data) then
|
||||
local parameters = {}
|
||||
for plate, data in pairs(Mileage.Data) do
|
||||
if data.owned then
|
||||
parameters[#parameters + 1] = { data.mileage, plate }
|
||||
end
|
||||
end
|
||||
|
||||
if next(parameters) then
|
||||
MySQL.prepare("UPDATE `owned_vehicles` SET `mileage` = ? WHERE `plate` = ?", parameters)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Mileage:Create(plate, mileage, owned, playerId)
|
||||
self.Data[plate] = { mileage = mileage, owned = owned }
|
||||
self:UpdateClient(mileage, playerId)
|
||||
end
|
||||
|
||||
function Mileage:Update(plate, mileage, playerId, kmh)
|
||||
if not self.Data[plate] then
|
||||
return
|
||||
end
|
||||
|
||||
if kmh then
|
||||
mileage = mileage / 1.61
|
||||
end
|
||||
|
||||
self.Data[plate].mileage = mileage
|
||||
if playerId then
|
||||
self:UpdateClient(mileage, playerId)
|
||||
end
|
||||
end
|
||||
|
||||
function Mileage:Exist(plate, playerId, kmh)
|
||||
if self.Data[plate] then
|
||||
local milage = self.Data[plate].mileage
|
||||
if kmh then
|
||||
milage = self.Data[plate].mileage * 1.61
|
||||
end
|
||||
self:UpdateClient(milage, playerId)
|
||||
return
|
||||
end
|
||||
self:Load(plate, playerId, kmh)
|
||||
end
|
||||
|
||||
-- Send date to client
|
||||
function Mileage:UpdateClient(mileage, playerId)
|
||||
TriggerClientEvent("esx_hud:UpdateMileage", playerId, mileage)
|
||||
end
|
||||
|
||||
RegisterNetEvent("esx_hud:EnteredVehicle", function(plate, kmh)
|
||||
local playerId = source
|
||||
Mileage:Exist(plate, playerId, kmh)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx_hud:ExitedVehicle", function(plate, mileage, kmh)
|
||||
Mileage:Update(plate, mileage, source, kmh)
|
||||
end)
|
||||
|
||||
-- Auto save every 5 min
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(1000 * 60 * 5)
|
||||
Mileage:Save()
|
||||
end
|
||||
end)
|
||||
|
||||
-- Auto save on resource stop
|
||||
AddEventHandler("onResourceStop", function(resourceName)
|
||||
if GetCurrentResourceName() ~= resourceName then
|
||||
return
|
||||
end
|
||||
Mileage:Save()
|
||||
end)
|
||||
|
||||
-- Auto save 10 sec before scheduled restart
|
||||
AddEventHandler("txAdmin:events:scheduledRestart", function(eventData)
|
||||
if eventData.secondsRemaining == 60 then
|
||||
CreateThread(function()
|
||||
Wait(50000)
|
||||
Mileage:Save()
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Auto save on txAdmin server stop
|
||||
AddEventHandler("txAdmin:events:serverShuttingDown", function()
|
||||
Mileage:Save()
|
||||
end)
|
||||
end
|
||||
64
resources/[esx_addons]/esx_hud/shared/config.lua
Normal file
@@ -0,0 +1,64 @@
|
||||
Config = {
|
||||
Locale = ESX.GetConfig().Locale or "en", -- If you want to change UI language texts you can do it here: web/src/assets/translate.json !!IMPORTANT that this can only be modified with the unbuilt version.
|
||||
Colors = {
|
||||
Info = {
|
||||
["money-text-color"] = "#0aad20",
|
||||
["bank-text-color"] = "#666666",
|
||||
["job-text-color"] = "#fb9b04",
|
||||
},
|
||||
Status = {
|
||||
healthBar = "red",
|
||||
armorBar = "blue",
|
||||
drinkBar = "lightblue",
|
||||
foodBar = "#fb9b04",
|
||||
},
|
||||
Speedo = {
|
||||
["segment-color"] = "#eee",
|
||||
["segment-progress-color"] = "#c97d03",
|
||||
["number-color"] = "#eee",
|
||||
["danger-color"] = "red",
|
||||
["danger-progress-color"] = "pink",
|
||||
["number-danger-color"] = "red",
|
||||
["speedo-progress-color"] = "#fb9b04",
|
||||
["damage-progress-color"] = "#0aad20",
|
||||
["speedo-all-texts"] = "#fb9b04",
|
||||
["engine-icon-color"] = "#fb9b04",
|
||||
["tempomat-icon-color"] = "#fb9b04",
|
||||
["light-icon-color"] = "#fb9b04",
|
||||
["door-icon-color"] = "#fb9b04",
|
||||
["fuel-icon-color"] = "#fb9b04",
|
||||
["fuel-level-color"] = "white",
|
||||
["mileage-level-color"] = "#eee",
|
||||
["unit-color"] = "white",
|
||||
["current-speed-color"] = "#fb9b04",
|
||||
["left-right-index-color"] = "#00B065",
|
||||
["damage-icon-color"] = "#0aad20",
|
||||
["speedo-background-color"] = "rgba(15,15,15,0.7)",
|
||||
["speedo-outer-circle-color"] = "rgba(30,30,30,0.7)",
|
||||
["speedo-nooble-color"] = "#fb9b04",
|
||||
["speedo-nooble-container"] = "rgb(30, 30, 30)",
|
||||
["speedo-seatbelt-icon-color"] = "#D22B2B",
|
||||
},
|
||||
},
|
||||
Disable = {
|
||||
Status = false,
|
||||
Vehicle = false,
|
||||
Weapon = false,
|
||||
Position = false,
|
||||
Voice = false,
|
||||
Money = false,
|
||||
Info = false,
|
||||
IndicatorSound = true, --vehicle index sound
|
||||
IndicatorSeatbeltSound = false, --seatbelt sound
|
||||
VehicleHandlers = false, -- Engine toggle, Indicator lights
|
||||
MinimapOnFoot = false,
|
||||
Needle = false,
|
||||
StatusPercent = false,
|
||||
CenterStatuses = false, -- true for above minimap, false for left side of the screen
|
||||
},
|
||||
Default = {
|
||||
ServerLogo = "https://esx.s3.fr-par.scw.cloud/blanc-800x800.png",
|
||||
Kmh = false,
|
||||
PassengerSpeedo = false, -- if this true , you can see speedometer if you don't driver
|
||||
},
|
||||
}
|
||||
6
resources/[esx_addons]/esx_hud/shared/main.lua
Normal file
@@ -0,0 +1,6 @@
|
||||
HUD = {}
|
||||
HUD.Data = {
|
||||
OnlinePlayers = 0,
|
||||
Weapon = {},
|
||||
Money = {},
|
||||
}
|
||||
BIN
resources/[esx_addons]/esx_hud/stream/minimap.gfx
Normal file
BIN
resources/[esx_addons]/esx_hud/stream/minimap.ytd
Normal file
1
resources/[esx_addons]/esx_hud/web/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
360
resources/[esx_addons]/esx_hud/web/DefaultDatas.js
Normal file
@@ -0,0 +1,360 @@
|
||||
import {
|
||||
ArmorIcon,
|
||||
DrinkIcon,
|
||||
FoodIcon,
|
||||
HealthIcon,
|
||||
OxygenIcon,
|
||||
StaminaIcon,
|
||||
} from "./src/assets/Icons";
|
||||
|
||||
let defaultConfig = {
|
||||
ServerLogo: "",
|
||||
Kmh: false,
|
||||
};
|
||||
|
||||
let disableDefaultConfig = {
|
||||
Status: false,
|
||||
Vehicle: false,
|
||||
Weapon: false,
|
||||
Position: false,
|
||||
Voice: false,
|
||||
Money: false,
|
||||
Info: false,
|
||||
IndicatorSound: false,
|
||||
IndicatorSeatbeltSound: false,
|
||||
VehicleHandlers: false,
|
||||
MinimapOnFoot: false,
|
||||
Needle: false,
|
||||
Kmh: true,
|
||||
StatusPercent: false,
|
||||
};
|
||||
|
||||
const progressColors = {
|
||||
healthBar: "red",
|
||||
armorBar: "blue",
|
||||
drinkBar: "lightblue",
|
||||
foodBar: "yellow",
|
||||
oxygenBar: "green",
|
||||
staminaBar: "purple",
|
||||
};
|
||||
|
||||
const vehDefaultData = {
|
||||
show: true,
|
||||
fuel: { level: 100, maxLevel: 100 },
|
||||
mileage: 5000,
|
||||
kmh: false,
|
||||
speed: 50,
|
||||
rpm: 100,
|
||||
damage: 100,
|
||||
vehType: "LAND",
|
||||
};
|
||||
const hudDefaultData = {
|
||||
playerId: 1,
|
||||
onlinePlayers: 150,
|
||||
serverLogo: "https://esx.s3.fr-par.scw.cloud/blanc-800x800.png",
|
||||
moneys: { bank: 75000, money: 100000 },
|
||||
weaponData: {
|
||||
use: true,
|
||||
image: "pistol",
|
||||
name: "WEAPON NAME",
|
||||
currentAmmo: 32,
|
||||
maxAmmo: 128,
|
||||
isWeaponMelee: false,
|
||||
},
|
||||
streetName: "",
|
||||
mic: false,
|
||||
};
|
||||
const progressLevels = {
|
||||
healthBar: 20,
|
||||
armorBar: 80,
|
||||
drinkBar: 40,
|
||||
foodBar: 80,
|
||||
oxygenBar: 100,
|
||||
staminaBar: 100,
|
||||
};
|
||||
|
||||
const defaultIndicators = {
|
||||
tempomat: true,
|
||||
door: false,
|
||||
light: false,
|
||||
engine: false,
|
||||
leftIndex: false,
|
||||
rightIndex: false,
|
||||
};
|
||||
|
||||
const defaultMenuButtons = [
|
||||
{
|
||||
name: "Status",
|
||||
path: "status",
|
||||
},
|
||||
{
|
||||
name: "Speedo",
|
||||
path: "speedo",
|
||||
},
|
||||
{
|
||||
name: "Settings",
|
||||
path: "settings",
|
||||
},
|
||||
];
|
||||
|
||||
const progressDefaultCircles = [
|
||||
{
|
||||
name: "healthBar",
|
||||
progressLevel: 100,
|
||||
color: "red",
|
||||
icon: HealthIcon,
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
name: "armorBar",
|
||||
progressLevel: 100,
|
||||
color: "blue",
|
||||
icon: ArmorIcon,
|
||||
},
|
||||
{
|
||||
name: "drinkBar",
|
||||
progressLevel: 100,
|
||||
color: "lightblue",
|
||||
icon: DrinkIcon,
|
||||
},
|
||||
{
|
||||
name: "foodBar",
|
||||
progressLevel: 100,
|
||||
color: "yellow",
|
||||
icon: FoodIcon,
|
||||
},
|
||||
{
|
||||
name: "oxygenBar",
|
||||
progressLevel: 100,
|
||||
color: "pink",
|
||||
icon: OxygenIcon,
|
||||
},
|
||||
{
|
||||
name: "staminaBar",
|
||||
progressLevel: 100,
|
||||
color: "green",
|
||||
icon: StaminaIcon,
|
||||
},
|
||||
];
|
||||
|
||||
const speedoDefaultColors = [
|
||||
{
|
||||
name: "segment-color",
|
||||
color: "#eee",
|
||||
},
|
||||
{
|
||||
name: "segment-progress-color",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
name: "number-color",
|
||||
color: "#eee",
|
||||
},
|
||||
{
|
||||
name: "danger-color",
|
||||
color: "#ff113a",
|
||||
},
|
||||
{
|
||||
name: "danger-progress-color",
|
||||
color: "pink",
|
||||
},
|
||||
{
|
||||
name: "number-danger-color",
|
||||
color: "#da0b64",
|
||||
},
|
||||
{
|
||||
name: "speedo-progress-color",
|
||||
color: "orange",
|
||||
},
|
||||
{
|
||||
name: "damage-progress-color",
|
||||
color: "#1be70d",
|
||||
},
|
||||
{
|
||||
name: "engine-icon-color",
|
||||
color: "#FEC32C",
|
||||
},
|
||||
|
||||
{
|
||||
name: "tempomat-icon-color",
|
||||
color: "#FEC32C",
|
||||
},
|
||||
{
|
||||
name: "light-icon-color",
|
||||
color: "#FEC32C",
|
||||
},
|
||||
{
|
||||
name: "door-icon-color",
|
||||
color: "#FEC32C",
|
||||
},
|
||||
{
|
||||
name: "fuel-icon-color",
|
||||
color: "white",
|
||||
},
|
||||
{
|
||||
name: "fuel-level-color",
|
||||
color: "pink",
|
||||
},
|
||||
{
|
||||
name: "mileage-level-color",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
name: "unit-color",
|
||||
color: "red",
|
||||
},
|
||||
{
|
||||
name: "current-speed-color",
|
||||
color: "pink",
|
||||
},
|
||||
{
|
||||
name: "left-right-index-color",
|
||||
color: "#00B065",
|
||||
},
|
||||
{
|
||||
name: "damage-icon-color",
|
||||
color: "white",
|
||||
},
|
||||
{
|
||||
name: "speedo-background-color",
|
||||
color: "rgba(0,0,0,.5)",
|
||||
},
|
||||
{
|
||||
name: "speedo-outer-circle-color",
|
||||
color: "#242222",
|
||||
},
|
||||
{
|
||||
name: "speedo-nooble-color",
|
||||
color: "#48a3cb",
|
||||
},
|
||||
{
|
||||
name: "speedo-nooble-container",
|
||||
color: "#1f2937",
|
||||
},
|
||||
{
|
||||
name: "speedo-seatbelt-icon-color",
|
||||
color: "#D22B2B",
|
||||
},
|
||||
];
|
||||
|
||||
const allColors = {
|
||||
Status: [
|
||||
{
|
||||
name: "healthBar",
|
||||
color: "red",
|
||||
},
|
||||
{
|
||||
name: "armorBar",
|
||||
color: "blue",
|
||||
},
|
||||
{
|
||||
name: "drinkBar",
|
||||
color: "lightblue",
|
||||
},
|
||||
{
|
||||
name: "foodBar",
|
||||
color: "yellow",
|
||||
},
|
||||
{
|
||||
name: "oxygenBar",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
name: "staminaBar",
|
||||
color: "purple",
|
||||
},
|
||||
],
|
||||
Speedo: [
|
||||
{
|
||||
name: "segment-color",
|
||||
color: "#eee",
|
||||
},
|
||||
{
|
||||
name: "number-color",
|
||||
color: "#eee",
|
||||
},
|
||||
{
|
||||
name: "danger-color",
|
||||
color: "#ff113a",
|
||||
},
|
||||
{
|
||||
name: "number-danger-color",
|
||||
color: "#da0b64",
|
||||
},
|
||||
{
|
||||
name: "speedo-progress-color",
|
||||
color: "orange",
|
||||
},
|
||||
{
|
||||
name: "damage-progress-color",
|
||||
color: "#1be70d",
|
||||
},
|
||||
{
|
||||
name: "engine-icon-color",
|
||||
color: "#FEC32C",
|
||||
},
|
||||
|
||||
{
|
||||
name: "tempomat-icon-color",
|
||||
color: "#FEC32C",
|
||||
},
|
||||
{
|
||||
name: "light-icon-color",
|
||||
color: "#FEC32C",
|
||||
},
|
||||
{
|
||||
name: "door-icon-color",
|
||||
color: "#FEC32C",
|
||||
},
|
||||
{
|
||||
name: "fuel-icon-color",
|
||||
color: "white",
|
||||
},
|
||||
{
|
||||
name: "fuel-level-color",
|
||||
color: "pink",
|
||||
},
|
||||
{
|
||||
name: "mileage-level-color",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
name: "unit-color",
|
||||
color: "red",
|
||||
},
|
||||
{
|
||||
name: "current-speed-color",
|
||||
color: "pink",
|
||||
},
|
||||
{
|
||||
name: "left-right-index-color",
|
||||
color: "#00B065",
|
||||
},
|
||||
{
|
||||
name: "damage-icon-color",
|
||||
color: "white",
|
||||
},
|
||||
{
|
||||
name: "speedo-background-color",
|
||||
color: "rgba(0,0,0,.5)",
|
||||
},
|
||||
{
|
||||
name: "speedo-outer-circle-color",
|
||||
color: "#242222",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export {
|
||||
disableDefaultConfig,
|
||||
defaultConfig,
|
||||
progressColors,
|
||||
vehDefaultData,
|
||||
hudDefaultData,
|
||||
progressLevels,
|
||||
defaultIndicators,
|
||||
defaultMenuButtons,
|
||||
progressDefaultCircles,
|
||||
allColors,
|
||||
speedoDefaultColors,
|
||||
};
|
||||
34
resources/[esx_addons]/esx_hud/web/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
## Usage
|
||||
|
||||
Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.
|
||||
|
||||
This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template.
|
||||
|
||||
```bash
|
||||
$ npm install # or pnpm install or yarn install
|
||||
```
|
||||
|
||||
### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm dev` or `npm start`
|
||||
|
||||
Runs the app in the development mode.<br>
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.<br>
|
||||
|
||||
### `npm run build`
|
||||
|
||||
Builds the app for production to the `dist` folder.<br>
|
||||
It correctly bundles Solid in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.<br>
|
||||
Your app is ready to be deployed!
|
||||
|
||||
## Deployment
|
||||
|
||||
You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)
|
||||
16
resources/[esx_addons]/esx_hud/web/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
|
||||
<title>Solid App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
<script src="/src/index.jsx" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
24
resources/[esx_addons]/esx_hud/web/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "vite-template-solid",
|
||||
"version": "0.1",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.13",
|
||||
"postcss": "^8.4.19",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"vite": "^3.0.9",
|
||||
"vite-plugin-solid": "^2.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@simonwep/pickr": "^1.8.2",
|
||||
"@solidjs/router": "^0.5.1",
|
||||
"solid-js": "^1.5.1"
|
||||
}
|
||||
}
|
||||
6
resources/[esx_addons]/esx_hud/web/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
90
resources/[esx_addons]/esx_hud/web/src/App.jsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import styles from './App.module.css';
|
||||
import {CircleProgressContainer} from "./assets/Components/CircleProgress";
|
||||
import {BottomInfoData} from "./assets/Components/BottomInfoData";
|
||||
import {InfoHud} from "./assets/Components/InfoHud";
|
||||
import {Speedo} from "./assets/Components/Speedo";
|
||||
import {createEffect, createSignal,Show} from "solid-js";
|
||||
import {
|
||||
disableDefaultConfig,
|
||||
defaultConfig
|
||||
} from "../DefaultDatas";
|
||||
import {SettingsPanel} from "./assets/Components/SettingsPanel/SettingsPanel";
|
||||
import {useHudStorageDispatch, useHudStorageState} from "./assets/Contexts/HudStorage";
|
||||
import {useSettingsStorageDispatch, useSettingsStorageState} from "./assets/Contexts/SettingsStorage";
|
||||
import {createStore} from "solid-js/store";
|
||||
import {setLang} from "./Utils/Translate";
|
||||
|
||||
|
||||
function App() {
|
||||
|
||||
const hudStorageState = useHudStorageState();
|
||||
const { updateStatus, updateSpeedo, updateHud , changeVoiceRange } = useHudStorageDispatch();
|
||||
|
||||
const { toggleShowPanel , changeThemeColors , setDefaultConfigs , handleLocalStorage } = useSettingsStorageDispatch();
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const settings = () => settingsStorageState.settings
|
||||
const showPanel = () => settingsStorageState.showPanel
|
||||
//check update lang after render component
|
||||
const [updateLang,setUpdateLang] = createSignal(false)
|
||||
const open = () =>{
|
||||
document.body.style.display = "flex";
|
||||
}
|
||||
|
||||
const close = () =>{
|
||||
document.body.style.display = "none";
|
||||
}
|
||||
|
||||
createEffect(()=>{
|
||||
window.addEventListener("message", function (event) {
|
||||
const type = event.data.type;
|
||||
const value = event.data.value;
|
||||
switch (type) {
|
||||
case "SHOW":
|
||||
value ? open() : close()
|
||||
break;
|
||||
case "SET_CONFIG_DATA":
|
||||
setLang(value["Locale"])
|
||||
setUpdateLang(true)
|
||||
setDefaultConfigs(value)
|
||||
const speedoColors = handleLocalStorage("speedoColors","get")
|
||||
if(!speedoColors){
|
||||
changeThemeColors(value["Colors"]["Speedo"])
|
||||
}
|
||||
break;
|
||||
case "VEH_HUD":
|
||||
updateSpeedo(value)
|
||||
break;
|
||||
case "STATUS_HUD":
|
||||
updateStatus(value)
|
||||
break;
|
||||
case "HUD_DATA":
|
||||
updateHud(value)
|
||||
break;
|
||||
case "VOICE_RANGE":
|
||||
changeVoiceRange(value)
|
||||
break;
|
||||
case "OPEN_SETTINGS":
|
||||
toggleShowPanel()
|
||||
break;
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return (
|
||||
<div class={styles.App}>
|
||||
<Show keyed when={updateLang()}>
|
||||
<SettingsPanel/>
|
||||
</Show>
|
||||
<Show keyed when={!settings().Status}>
|
||||
<CircleProgressContainer/>
|
||||
</Show>
|
||||
<BottomInfoData/>
|
||||
<InfoHud/>
|
||||
<Show keyed when={!settings().Vehicle}>
|
||||
<Speedo/>
|
||||
</Show>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
33
resources/[esx_addons]/esx_hud/web/src/App.module.css
Normal file
@@ -0,0 +1,33 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
animation: logo-spin infinite 20s linear;
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #b318f0;
|
||||
}
|
||||
|
||||
@keyframes logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
25
resources/[esx_addons]/esx_hud/web/src/Utils/Nui.js
Normal file
@@ -0,0 +1,25 @@
|
||||
export const Nui = {
|
||||
async send(event, data = {}) {
|
||||
try {
|
||||
const resp = await fetch(`https://${GetParentResourceName()}/${event}`, {
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
return await resp.json();
|
||||
} catch (error) {
|
||||
throw Error(`Failed to fetch NUI callback ${event}! (${error})`);
|
||||
}
|
||||
},
|
||||
|
||||
emulate(type, data = null) {
|
||||
window.dispatchEvent(
|
||||
new MessageEvent("message", {
|
||||
data: { type, data },
|
||||
}),
|
||||
);
|
||||
},
|
||||
};
|
||||
34
resources/[esx_addons]/esx_hud/web/src/Utils/Translate.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import TranslateData from "../assets/translate.json";
|
||||
|
||||
/**
|
||||
* Converts the key into dynamic language text
|
||||
* @param translateKey current translated string
|
||||
* @param translateObjectName current translate object name (Status,Speedo,Settings)
|
||||
* @param defaultKey (optional) return default string if doesn't exist key
|
||||
* @return {*}
|
||||
*/
|
||||
let lang = "en";
|
||||
export const translate = (
|
||||
translateKey,
|
||||
translateObjectName = "General",
|
||||
defaultKey = null,
|
||||
) => {
|
||||
if (!TranslateData[lang][translateObjectName][translateKey.toLowerCase()]) {
|
||||
console.warn(
|
||||
`Doesn't exist translate key: ${translateKey.toLowerCase()} in ${translateObjectName} translate object`,
|
||||
);
|
||||
return defaultKey ? defaultKey : translateKey;
|
||||
}
|
||||
return TranslateData[lang][translateObjectName][translateKey.toLowerCase()];
|
||||
};
|
||||
|
||||
export function setLang(currentLang) {
|
||||
let newLang = currentLang.length > 0 ? currentLang : "en";
|
||||
if (!TranslateData[currentLang]) {
|
||||
console.warn(
|
||||
`There is no such language type! Current language type: ${currentLang} If you want add other lang you can do here: web/src/assets/translate.json !!IMPORTANT this file only see with the unbuilt version.`,
|
||||
);
|
||||
newLang = "en";
|
||||
}
|
||||
lang = newLang;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import {For} from "solid-js";
|
||||
import {useHudStorageDispatch, useHudStorageState} from "../Contexts/HudStorage";
|
||||
import {useSettingsStorageState} from "../Contexts/SettingsStorage";
|
||||
|
||||
const MicIcon = (props) => {
|
||||
const mic = () => props.state ? 'orange' : 'white'
|
||||
const radio = () => props.radio ? 'red': 'white'
|
||||
|
||||
return(
|
||||
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="ease-in duration-200" d="M6.5625 3.9375C6.5625 2.89321 6.97734 1.89169 7.71577 1.15327C8.45419 0.414843 9.45571 0 10.5 0C11.5443 0 12.5458 0.414843 13.2842 1.15327C14.0227 1.89169 14.4375 2.89321 14.4375 3.9375V10.5C14.4375 11.5443 14.0227 12.5458 13.2842 13.2842C12.5458 14.0227 11.5443 14.4375 10.5 14.4375C9.45571 14.4375 8.45419 14.0227 7.71577 13.2842C6.97734 12.5458 6.5625 11.5443 6.5625 10.5V3.9375Z" fill={props.state ? mic() : radio()}/>
|
||||
<path class="ease-in duration-200" d="M4.59375 8.53125C4.7678 8.53125 4.93472 8.60039 5.05779 8.72346C5.18086 8.84653 5.25 9.01345 5.25 9.1875V10.5C5.25 11.8924 5.80312 13.2277 6.78769 14.2123C7.77226 15.1969 9.10761 15.75 10.5 15.75C11.8924 15.75 13.2277 15.1969 14.2123 14.2123C15.1969 13.2277 15.75 11.8924 15.75 10.5V9.1875C15.75 9.01345 15.8191 8.84653 15.9422 8.72346C16.0653 8.60039 16.2322 8.53125 16.4062 8.53125C16.5803 8.53125 16.7472 8.60039 16.8703 8.72346C16.9934 8.84653 17.0625 9.01345 17.0625 9.1875V10.5C17.0625 12.1269 16.4582 13.6958 15.3669 14.9023C14.2756 16.1088 12.775 16.867 11.1562 17.0297V19.6875H15.0938C15.2678 19.6875 15.4347 19.7566 15.5578 19.8797C15.6809 20.0028 15.75 20.1697 15.75 20.3438C15.75 20.5178 15.6809 20.6847 15.5578 20.8078C15.4347 20.9309 15.2678 21 15.0938 21H5.90625C5.7322 21 5.56528 20.9309 5.44221 20.8078C5.31914 20.6847 5.25 20.5178 5.25 20.3438C5.25 20.1697 5.31914 20.0028 5.44221 19.8797C5.56528 19.7566 5.7322 19.6875 5.90625 19.6875H9.84375V17.0297C8.22502 16.867 6.72443 16.1088 5.63309 14.9023C4.54175 13.6958 3.93748 12.1269 3.9375 10.5V9.1875C3.9375 9.01345 4.00664 8.84653 4.12971 8.72346C4.25278 8.60039 4.4197 8.53125 4.59375 8.53125Z" fill={props.state ? mic() : radio()}/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
const GpsIcon = () => <svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.5 2C7.45929 2 5 4.817 5 8.3C5 13.025 10.5 20 10.5 20C10.5 20 16 13.025 16 8.3C16 4.817 13.5407 2 10.5 2ZM10.5 10.55C9.41571 10.55 8.53571 9.542 8.53571 8.3C8.53571 7.058 9.41571 6.05 10.5 6.05C11.5843 6.05 12.4643 7.058 12.4643 8.3C12.4643 9.542 11.5843 10.55 10.5 10.55Z" fill="white"/>
|
||||
</svg>
|
||||
|
||||
const Point = (props) =>{
|
||||
return(
|
||||
<div class={`${props.state ? 'bg-green-400' : 'bg-green-900'} ease-in duration-500 w-2 h-2 rounded-full border border-solid border-gray-900`}></div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export const BottomInfoData = (props) => {
|
||||
|
||||
const hudStorageState = useHudStorageState();
|
||||
const { currentMicRangeStatus } = useHudStorageDispatch();
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const settings = () => settingsStorageState.settings
|
||||
|
||||
const hud = () => hudStorageState.hud
|
||||
const voice = () => hud().voice
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2 absolute left-1/4 bottom-10">
|
||||
|
||||
<Show keyed when={!settings().Voice}>
|
||||
<div className="flex gap-2 items-center">
|
||||
<MicIcon state={voice().mic} radio={voice().radio}/>
|
||||
<div class="flex flex-col gap-1 -rotate-180">
|
||||
<For each={currentMicRangeStatus()}>{(range, i) =>
|
||||
<Point state={range}/>
|
||||
}</For>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Show keyed when={!settings().Position}>
|
||||
<div className="flex gap-4 items-center">
|
||||
<GpsIcon/>
|
||||
<p className="font-bold text-white">{hud().streetName}</p>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
import {createMemo, Show} from "solid-js";
|
||||
import {useHudStorageState} from "../Contexts/HudStorage";
|
||||
import {useSettingsStorageDispatch, useSettingsStorageState} from "../Contexts/SettingsStorage";
|
||||
|
||||
export const CircleProgress = (props) => {
|
||||
return (
|
||||
<div className={`w-10 flex flex-col justify-center items-center`} >
|
||||
<div className="relative w-10 h-10">
|
||||
<svg width="40" height="40" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle className="ease-in duration-300" r="15" cx="20" cy="20" stroke={props?.color} stroke-opacity="0.1" fill="transparent" stroke-width={props?.circleWidth} stroke-dashoffset="0"></circle>
|
||||
<circle className="ease-in duration-300" id="bar" r="15" cx="20" cy="20" fill-opacity="0.3" fill={props?.color} stroke-dasharray={`${props?.progressLevel} 100`} stroke-width={props?.circleWidth} stroke={props?.color} stroke-dashoffset="0"></circle>
|
||||
</svg>
|
||||
{props?.icon}
|
||||
</div>
|
||||
<Show keyed when={props?.showPercent}>
|
||||
<p className="text-xs font-normal text-white">{props.progressLevel}%</p>
|
||||
</Show>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const CircleProgressContainer = (props) =>{
|
||||
|
||||
const hudStorageState = useHudStorageState();
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const { getCurrentColor } = useSettingsStorageDispatch();
|
||||
const showSpeedo = () => hudStorageState.speedo.show
|
||||
const settings = () => settingsStorageState.settings
|
||||
const currentWidth = () => settingsStorageState.currentCircleWidth
|
||||
|
||||
const getGoodClassName = createMemo(()=>{
|
||||
if(!showSpeedo()){
|
||||
if(settings().MinimapOnFoot){
|
||||
return 'flex-col-status'
|
||||
}
|
||||
}
|
||||
if(!settings().CenterStatuses){
|
||||
return 'center-statuses'
|
||||
}
|
||||
return 'flex-status'
|
||||
})
|
||||
|
||||
return(
|
||||
<Show when={!settings().Status} keyed>
|
||||
<div className={getGoodClassName()}>
|
||||
<For each={hudStorageState.status}>{(progress, i) =>
|
||||
<Show keyed when={progress.progressLevel > 0}>
|
||||
<CircleProgress showPercent={!settings().StatusPercent} icon={progress.icon} progressLevel={progress.progressLevel} color={getCurrentColor(progress.name,"statusColors")} circleWidth={currentWidth()} />
|
||||
</Show>
|
||||
}</For>
|
||||
</div>
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.moneyTextColor {
|
||||
color: var(--money-text-color);
|
||||
}
|
||||
|
||||
.bankTextColor {
|
||||
color: var(--bank-text-color);
|
||||
}
|
||||
|
||||
.jobTextColor {
|
||||
color: var(--job-text-color);
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
import {Routes, Route, useNavigate, A} from "@solidjs/router"
|
||||
import {Settings} from "./pages/Settings";
|
||||
import {
|
||||
defaultMenuButtons
|
||||
} from "../../../../DefaultDatas";
|
||||
import {SpeedoTemplate} from "./pages/SpeedoTemplate";
|
||||
import {Status} from "./pages/Status";
|
||||
import {createSignal, onMount, Show} from "solid-js";
|
||||
import {useSettingsStorageDispatch, useSettingsStorageState} from "../../Contexts/SettingsStorage";
|
||||
import {Nui} from "../../../Utils/Nui";
|
||||
import {translate} from "../../../Utils/Translate";
|
||||
|
||||
const MainPage = (props) =>{
|
||||
const currentPath = () => props?.currentPath()
|
||||
return(
|
||||
<div class="flex gap-4 justify-center border-b-2 border-[#0087D0] border-solid p-4">
|
||||
<For each={defaultMenuButtons}>{(menu, i) =>
|
||||
<A className={`p-2 ${currentPath() === menu.path ? 'bg-blue-800' : 'bg-sky-400'} uppercase rounded-md bg-[#0087D0] hover:scale-125 ease-out duration-300`} href={`/${menu.path}`} onClick={() => props?.onMenuClick(menu)}>{translate(menu.name)}</A>
|
||||
}</For>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ExitIcon = (props) => <svg width="30" height="30" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512"><path class="fill-gray-800 hover:fill-red-700 hover:ease-in duration-100" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"/></svg>
|
||||
|
||||
const ResetIcon = () => <svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="white" d="M105.1 202.6c7.7-21.8 20.2-42.3 37.8-59.8c62.5-62.5 163.8-62.5 226.3 0L386.3 160H336c-17.7 0-32 14.3-32 32s14.3 32 32 32H463.5c0 0 0 0 0 0h.4c17.7 0 32-14.3 32-32V64c0-17.7-14.3-32-32-32s-32 14.3-32 32v51.2L414.4 97.6c-87.5-87.5-229.3-87.5-316.8 0C73.2 122 55.6 150.7 44.8 181.4c-5.9 16.7 2.9 34.9 19.5 40.8s34.9-2.9 40.8-19.5zM39 289.3c-5 1.5-9.8 4.2-13.7 8.2c-4 4-6.7 8.8-8.1 14c-.3 1.2-.6 2.5-.8 3.8c-.3 1.7-.4 3.4-.4 5.1V448c0 17.7 14.3 32 32 32s32-14.3 32-32V396.9l17.6 17.5 0 0c87.5 87.4 229.3 87.4 316.7 0c24.4-24.4 42.1-53.1 52.9-83.7c5.9-16.7-2.9-34.9-19.5-40.8s-34.9 2.9-40.8 19.5c-7.7 21.8-20.2 42.3-37.8 59.8c-62.5 62.5-163.8 62.5-226.3 0l-.1-.1L125.6 352H176c17.7 0 32-14.3 32-32s-14.3-32-32-32H48.4c-1.6 0-3.2 .1-4.8 .3s-3.1 .5-4.6 1z"/></svg>
|
||||
|
||||
const SaveIcon = () => <svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="white" d="M64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V173.3c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32H64zm0 96c0-17.7 14.3-32 32-32H288c17.7 0 32 14.3 32 32v64c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V128zM224 416c-35.3 0-64-28.7-64-64s28.7-64 64-64s64 28.7 64 64s-28.7 64-64 64z"/></svg>
|
||||
|
||||
const SaveResetButtons = (props) =>{
|
||||
|
||||
const click = () => props?.onSaveAndResetButtonClick()
|
||||
const clickReset = () => props?.onSaveAndResetButtonClick("reset")
|
||||
const name = () => props?.selectedName
|
||||
const title = () => props?.currentSelectedMenu
|
||||
const showEdit = () => props?.showEdit
|
||||
const toggleShowPanel = () => props?.toggleShowPanel()
|
||||
|
||||
//Exit right top corner
|
||||
const handleClickClose = () => {
|
||||
toggleShowPanel()
|
||||
Nui.send("closePanel")
|
||||
}
|
||||
|
||||
document.addEventListener('keyup',function (e){
|
||||
if(e.key === "Escape"){
|
||||
handleClickClose()
|
||||
}
|
||||
})
|
||||
|
||||
return(
|
||||
<>
|
||||
<div class="relative flex justify-evenly items-center mt-5 z-10">
|
||||
<button class="p-2 bg-red-700 rounded-md hover:scale-125 ease-out duration-300" onClick={clickReset}>
|
||||
<div class="flex gap-2 items-center justify-center">
|
||||
<ResetIcon/>
|
||||
{translate("reset")}
|
||||
</div>
|
||||
</button>
|
||||
<div class="uppercase text-3xl">{title().length > 0 ? translate(title()) : ''}</div>
|
||||
<button class="p-2 bg-green-700 rounded-md hover:scale-125 ease-out duration-300" onClick={click}>
|
||||
<div class="flex gap-2 items-center justify-center">
|
||||
<SaveIcon/>
|
||||
{translate("save")}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<button class="absolute top-5 right-5" onClick={handleClickClose}>
|
||||
<ExitIcon/>
|
||||
</button>
|
||||
<Show keyed when={showEdit()}>
|
||||
<h1 class="mb-5 mt-5 font-bold">
|
||||
{
|
||||
name().length > 0 ? `${translate("currentedit")} ${name()}` : translate("info")
|
||||
}
|
||||
</h1>
|
||||
</Show>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// if detect changes return true else return false
|
||||
const checkObjectValueChanges = (checkedObject,defaultObject) =>{
|
||||
let changes = false
|
||||
Object.keys(defaultObject).forEach((data)=>{
|
||||
checkedObject.forEach((status)=>{
|
||||
if(status.name === data){
|
||||
if(status.color !== defaultObject[data]){
|
||||
changes = true
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
return changes
|
||||
}
|
||||
|
||||
export const SettingsPanel = () =>{
|
||||
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const [showEdit,setShowEdit] = createSignal(true)
|
||||
const [currentPath,setCurrentPath] = createSignal('status')
|
||||
const { setSelectedMenu,resetColors ,saveColors,saveSettings,resetSettings,setSelectedElement, toggleShowPanel } = useSettingsStorageDispatch();
|
||||
const currentSelectedElementName = () => settingsStorageState.selectedElementName
|
||||
const showPanel = () => settingsStorageState.showPanel
|
||||
|
||||
const selectedMenuName = () => settingsStorageState.selectedMenuName
|
||||
const navigate = useNavigate()
|
||||
|
||||
const handleMenuClick = (currentMenu) =>{
|
||||
if(currentMenu.name === selectedMenuName()){
|
||||
return
|
||||
}
|
||||
//Remove picker element in DOM if change route path
|
||||
const allPickerElement = document.querySelectorAll('.custom-colorpicker')
|
||||
if(allPickerElement.length > 0)
|
||||
allPickerElement.forEach(e => e.remove());
|
||||
|
||||
setSelectedMenu(currentMenu.name) //TODO: NEW
|
||||
setSelectedElement("")
|
||||
setShowEdit(currentMenu.name !== "Settings")
|
||||
setCurrentPath(currentMenu.path)
|
||||
}
|
||||
|
||||
onMount(()=>{
|
||||
handleMenuClick({name: "Status", path:"status"})
|
||||
navigate('/status', { replace: true });
|
||||
})
|
||||
|
||||
const handleClickSaveAndReset = (type) =>{
|
||||
setSelectedElement('')
|
||||
if(type === "reset"){
|
||||
if(selectedMenuName() === "Settings"){
|
||||
resetSettings()
|
||||
return;
|
||||
}
|
||||
resetColors()
|
||||
return;
|
||||
}
|
||||
|
||||
if(selectedMenuName() === "Settings"){
|
||||
saveSettings()
|
||||
return;
|
||||
}
|
||||
saveColors()
|
||||
}
|
||||
|
||||
return(
|
||||
<>
|
||||
<div class={`relative bg-[#17191A] w-[650px] rounded-[25px] pb-4 ease-in duration-500 z-30 ${showPanel() ? 'slideDown' : 'slideUp'}`}>
|
||||
<MainPage currentPath={currentPath} onMenuClick={handleMenuClick}/>
|
||||
<SaveResetButtons toggleShowPanel={toggleShowPanel} showEdit={showEdit()} currentSelectedMenu={selectedMenuName()} selectedName={currentSelectedElementName()} onSaveAndResetButtonClick={handleClickSaveAndReset}/>
|
||||
<Routes>
|
||||
<Route path="/status" component={Status}/>
|
||||
<Route path="/speedo" component={SpeedoTemplate}/>
|
||||
<Route path="/settings" component={Settings}/>
|
||||
</Routes>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
import {onMount} from "solid-js";
|
||||
import {useSettingsStorageDispatch, useSettingsStorageState} from "../../../Contexts/SettingsStorage";
|
||||
import '@simonwep/pickr/dist/themes/classic.min.css';
|
||||
import '@simonwep/pickr/dist/themes/monolith.min.css'; // 'monolith' theme
|
||||
import '@simonwep/pickr/dist/themes/nano.min.css'; // 'nano' theme
|
||||
import Pickr from '@simonwep/pickr/dist/pickr.es5.min';
|
||||
|
||||
const ColorPaletteIcon = () => <svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="white" d="M512 256c0 .9 0 1.8 0 2.7c-.4 36.5-33.6 61.3-70.1 61.3H344c-26.5 0-48 21.5-48 48c0 3.4 .4 6.7 1 9.9c2.1 10.2 6.5 20 10.8 29.9c6.1 13.8 12.1 27.5 12.1 42c0 31.8-21.6 60.7-53.4 62c-3.5 .1-7 .2-10.6 .2C114.6 512 0 397.4 0 256S114.6 0 256 0S512 114.6 512 256zM128 288c0-17.7-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32s32-14.3 32-32zm0-96c17.7 0 32-14.3 32-32s-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32zM288 96c0-17.7-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32s32-14.3 32-32zm96 96c17.7 0 32-14.3 32-32s-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32z"/></svg>
|
||||
|
||||
export const ColorPicker = (props) => {
|
||||
|
||||
const { setCurrentPickedColor, setSelectedElement } = useSettingsStorageDispatch();
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const selectedMenuName = () => settingsStorageState.selectedMenuName
|
||||
|
||||
let colorpicker
|
||||
|
||||
onMount(()=>{
|
||||
colorpicker = Pickr.create({
|
||||
// Selector or element which will be replaced with the actual color-picker.
|
||||
// Can be a HTMLElement.
|
||||
el: `#${props?.name}-colorpicker`,
|
||||
|
||||
// Where the pickr-app should be added as child.
|
||||
container: 'body',
|
||||
|
||||
// Which theme you want to use. Can be 'classic', 'monolith' or 'nano'
|
||||
theme: 'classic',
|
||||
|
||||
// Nested scrolling is currently not supported and as this would be really sophisticated to add this
|
||||
// it's easier to set this to true which will hide pickr if the user scrolls the area behind it.
|
||||
closeOnScroll: false,
|
||||
|
||||
// Custom class which gets added to the pcr-app. Can be used to apply custom styles.
|
||||
appClass: 'custom-colorpicker',
|
||||
|
||||
// Don't replace 'el' Element with the pickr-button, instead use 'el' as a button.
|
||||
// If true, appendToBody will also be automatically true.
|
||||
useAsButton: true,
|
||||
|
||||
// Size of gap between pickr (widget) and the corresponding reference (button) in px
|
||||
padding: 8,
|
||||
|
||||
// If true pickr won't be floating, and instead will append after the in el resolved element.
|
||||
// It's possible to hide it via .hide() anyway.
|
||||
inline: false,
|
||||
|
||||
// If true, pickr will be repositioned automatically on page scroll or window resize.
|
||||
// Can be set to false to make custom positioning easier.
|
||||
autoReposition: true,
|
||||
|
||||
// Defines the direction in which the knobs of hue and opacity can be moved.
|
||||
// 'v' => opacity- and hue-slider can both only moved vertically.
|
||||
// 'hv' => opacity-slider can be moved horizontally and hue-slider vertically.
|
||||
// Can be used to apply custom layouts
|
||||
sliders: 'v',
|
||||
|
||||
// Start state. If true 'disabled' will be added to the button's classlist.
|
||||
disabled: false,
|
||||
|
||||
// If true, the user won't be able to adjust any opacity.
|
||||
// Opacity will be locked at 1 and the opacity slider will be removed.
|
||||
// The HSVaColor object also doesn't contain an alpha, so the toString() methods just
|
||||
// print HSV, HSL, RGB, HEX, etc.
|
||||
lockOpacity: false,
|
||||
|
||||
// Precision of output string (only effective if components.interaction.input is true)
|
||||
outputPrecision: 0,
|
||||
|
||||
// Defines change/save behavior:
|
||||
// - to keep current color in place until Save is pressed, set to `true`,
|
||||
// - to apply color to button and preview (save) in sync with each change
|
||||
// (from picker or palette), set to `false`.
|
||||
comparison: true,
|
||||
|
||||
// Default color. If you're using a named color such as red, white ... set
|
||||
// a value for defaultRepresentation too as there is no button for named-colors.
|
||||
default: '#42445a',
|
||||
|
||||
// Optional color swatches. When null, swatches are disabled.
|
||||
// Types are all those which can be produced by pickr e.g. hex(a), hsv(a), hsl(a), rgb(a), cmyk, and also CSS color names like 'magenta'.
|
||||
// Example: swatches: ['#F44336', '#E91E63', '#9C27B0', '#673AB7'],
|
||||
swatches: ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#8ad4eb','#fd625e','#ffffff','#000000','#a66999','#fe9666','#f2c80f','#C0C0C0','#808080','#000080','#0000FF','#008080','#00FFFF'],
|
||||
|
||||
// Default color representation of the input/output textbox.
|
||||
// Valid options are `HEX`, `RGBA`, `HSVA`, `HSLA` and `CMYK`.
|
||||
defaultRepresentation: 'HEX',
|
||||
|
||||
// Option to keep the color picker always visible.
|
||||
// You can still hide / show it via 'pickr.hide()' and 'pickr.show()'.
|
||||
// The save button keeps its functionality, so still fires the onSave event when clicked.
|
||||
showAlways: false,
|
||||
|
||||
// Close pickr with a keypress.
|
||||
// Default is 'Escape'. Can be the event key or code.
|
||||
// (see: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)
|
||||
closeWithKey: 'Escape',
|
||||
|
||||
// Defines the position of the color-picker.
|
||||
// Any combinations of top, left, bottom or right with one of these optional modifiers: start, middle, end
|
||||
// Examples: top-start / right-end
|
||||
// If clipping occurs, the color picker will automatically choose its position.
|
||||
// Pickr uses https://github.com/Simonwep/nanopop as positioning-engine.
|
||||
position: selectedMenuName() === "Speedo" ? 'left-middle':'right-middle',
|
||||
|
||||
// Enables the ability to change numbers in an input field with the scroll-wheel.
|
||||
// To use it set the cursor on a position where a number is and scroll, use ctrl to make steps of five
|
||||
adjustableNumbers: true,
|
||||
|
||||
// Show or hide specific components.
|
||||
// By default only the palette (and the save button) is visible.
|
||||
components: {
|
||||
|
||||
// Defines if the palette itself should be visible.
|
||||
// Will be overwritten with true if preview, opacity or hue are true
|
||||
palette: true,
|
||||
|
||||
preview: false, // Display comparison between previous state and new color
|
||||
opacity: true, // Display opacity slider
|
||||
hue: true, // Display hue slider
|
||||
|
||||
// show or hide components on the bottom interaction bar.
|
||||
interaction: {
|
||||
|
||||
// Buttons, if you disable one but use the format in default: or setColor() - set the representation-type too!
|
||||
hex: true, // Display 'input/output format as hex' button (hexadecimal representation of the rgba value)
|
||||
rgba: true, // Display 'input/output format as rgba' button (red green blue and alpha)
|
||||
hsla: false, // Display 'input/output format as hsla' button (hue saturation lightness and alpha)
|
||||
hsva: false, // Display 'input/output format as hsva' button (hue saturation value and alpha)
|
||||
cmyk: false, // Display 'input/output format as cmyk' button (cyan mangenta yellow key )
|
||||
|
||||
input: true, // Display input/output textbox which shows the selected color value.
|
||||
// the format of the input is determined by defaultRepresentation,
|
||||
// and can be changed by the user with the buttons set by hex, rgba, hsla, etc (above).
|
||||
cancel: false, // Display Cancel Button, resets the color to the previous state
|
||||
clear: false, // Display Clear Button; same as cancel, but keeps the window open
|
||||
save: false, // Display Save Button,
|
||||
},
|
||||
},
|
||||
|
||||
// Translations, these are the default values.
|
||||
i18n: {
|
||||
|
||||
// Strings visible in the UI
|
||||
'ui:dialog': 'color picker dialog',
|
||||
'btn:toggle': 'toggle color picker dialog',
|
||||
'btn:swatch': 'color swatch',
|
||||
'btn:last-color': 'use previous color',
|
||||
'btn:save': 'Save',
|
||||
'btn:cancel': 'Cancel',
|
||||
'btn:clear': 'Clear',
|
||||
|
||||
// Strings used for aria-labels
|
||||
'aria:btn:save': 'save and close',
|
||||
'aria:btn:cancel': 'cancel and close',
|
||||
'aria:btn:clear': 'clear and close',
|
||||
'aria:input': 'color input field',
|
||||
'aria:palette': 'color selection area',
|
||||
'aria:hue': 'hue selection slider',
|
||||
'aria:opacity': 'selection slider'
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const handleClick = () =>{
|
||||
setSelectedElement(props?.name)
|
||||
colorpicker.on('init',instance =>{
|
||||
}).on('change',(color, source, instance) =>{
|
||||
setCurrentPickedColor(color.toHEXA().toString())
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button id={`${props?.name}-colorpicker`} class={`${props?.isActive ? 'bg-red-400': ''} p-2 bg-[#0087D0] rounded-md hover:scale-125 ease-out duration-300`} onClick={handleClick}>
|
||||
<ColorPaletteIcon/>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
import {createMemo} from "solid-js";
|
||||
import {useSettingsStorageDispatch, useSettingsStorageState} from "../../../Contexts/SettingsStorage";
|
||||
import {Nui} from "../../../../Utils/Nui";
|
||||
import {translate} from "../../../../Utils/Translate";
|
||||
|
||||
const CheckBox = (props) =>{
|
||||
return(
|
||||
<div class="form-check flex">
|
||||
<input class="form-check-input appearance-none h-4 w-4 border border-gray-300 rounded-sm bg-gray-800 checked:bg-[#0087D0] checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer" type="checkbox" value="" id={props?.name} checked={!props?.state} onClick={props?.click}/>
|
||||
<label class="form-check-label w-[75%]" for={props?.name}>
|
||||
{props?.name}
|
||||
</label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const RadioButton = (props) =>{
|
||||
return(
|
||||
<div class="form-radio-check flex">
|
||||
<input class="form-radio-check-input appearance-none rounded-full h-4 w-4 border border-gray-300 bg-gray-800 checked:bg-[#0087D0] checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer" type="radio" name="flexRadioDefault" id={props?.name} checked={props?.state} onClick={props?.click}/>
|
||||
<label class="form-check-label inline-block" for={props?.name}>
|
||||
{props?.name}
|
||||
</label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const Settings = () => {
|
||||
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const {setSettingsByName} = useSettingsStorageDispatch();
|
||||
|
||||
const settingsData = () => settingsStorageState.settings
|
||||
const defaultConfigs = () => settingsStorageState.defaultConfigs
|
||||
|
||||
const radioButtonClick = (currentUnit) =>{
|
||||
const unit = currentUnit === "KMH"
|
||||
setSettingsByName("Kmh", unit, "defaultConfigs")
|
||||
Nui.send("unitChanged",{unit})
|
||||
}
|
||||
|
||||
const handleClick = (name, value) =>{
|
||||
if(name === "MinimapOnFoot"){
|
||||
Nui.send("minimapSettingChanged",{changed: !value})
|
||||
}
|
||||
setSettingsByName(name)
|
||||
}
|
||||
|
||||
|
||||
//skip KMH key
|
||||
const formatDisableData = createMemo(() => Object.keys(settingsData()).filter((configName)=> configName !== "Kmh"))
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="grid grid-cols-2 p-5 mt-10 gap-2">
|
||||
<For each={formatDisableData()}>{(configName, i) =>
|
||||
<CheckBox name={translate(configName,"Settings")} state={settingsData()[configName]} click={()=>{handleClick(configName,settingsData()[configName])}}/>
|
||||
}</For>
|
||||
</div>
|
||||
<div class="flex gap-4 p-5">
|
||||
<h1>{translate("changeunit","Settings","Change unit:")}</h1>
|
||||
<RadioButton name={translate("kmh","Settings","KMH")} state={defaultConfigs().Kmh} click={()=>radioButtonClick("KMH")}/>
|
||||
<RadioButton name={translate("mph","Settings","MPH")} state={!defaultConfigs().Kmh} click={()=>radioButtonClick("MPH")}/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
import {Speedo} from "../../Speedo";
|
||||
import {speedoDefaultColors, vehDefaultData} from "../../../../../DefaultDatas";
|
||||
import {createStore} from "solid-js/store";
|
||||
import {ColorPicker} from "./ColorPicker";
|
||||
import {useSettingsStorageDispatch, useSettingsStorageState} from "../../../Contexts/SettingsStorage";
|
||||
import {translate} from "../../../../Utils/Translate";
|
||||
import { RangeSlider } from "./Status";
|
||||
|
||||
export const SpeedoTemplate = (props) => {
|
||||
|
||||
const [speedoColors, setSpeedoColors] = createStore(speedoDefaultColors)
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const { setCurrentSpeedoSize } = useSettingsStorageDispatch();
|
||||
const currentElement = () => settingsStorageState.selectedElementName
|
||||
const currentSize = () => settingsStorageState.currentSpeedoSize
|
||||
|
||||
return (
|
||||
<div class="flex flex-col gap-5">
|
||||
<div class="flex px-5 gap-[3rem]">
|
||||
<div class="relative z-10 p-2 flex flex-col gap-6 overflow-auto max-h-72">
|
||||
<For each={speedoColors}>{(progress, i) =>
|
||||
<div class="flex justify-between items-center gap-2">
|
||||
<h2 class="uppercase">{translate(progress.name,"Speedo")}</h2>
|
||||
<ColorPicker isActive={currentElement() === progress.name} name={progress.name}/>
|
||||
</div>
|
||||
}</For>
|
||||
</div>
|
||||
<div class="flex items-center justify-center">
|
||||
<Speedo template="true" vehData={vehDefaultData}/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<RangeSlider currentSize={currentSize()} setSize={setCurrentSpeedoSize} name={translate("resize-speedo","Speedo")} defaultValue={0.9} options={{min: 0.1, max:1.0, step: 0.1}}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
import {progressDefaultCircles} from "../../../../../DefaultDatas";
|
||||
import {CircleProgress} from "../../CircleProgress";
|
||||
import {ColorPicker} from "./ColorPicker";
|
||||
import {createStore, produce} from "solid-js/store";
|
||||
import {useSettingsStorageDispatch, useSettingsStorageState} from "../../../Contexts/SettingsStorage";
|
||||
import {createEffect, onMount} from "solid-js";
|
||||
import {translate} from "../../../../Utils/Translate";
|
||||
|
||||
|
||||
export const RangeSlider = (props) =>{
|
||||
|
||||
const options = () => props?.options
|
||||
|
||||
const handleChange = (e) =>{
|
||||
props?.setSize(e.target.value)
|
||||
}
|
||||
|
||||
|
||||
return(
|
||||
<div class="flex items-center justify-center gap-4 relative pt-1">
|
||||
<label for="rangeWidth" class="form-label uppercase">{props?.name}</label>
|
||||
<input
|
||||
type="range"
|
||||
class="
|
||||
form-range
|
||||
appearance-none
|
||||
rounded-full
|
||||
w-1/2
|
||||
h-2
|
||||
p-0
|
||||
bg-[#0087D0]
|
||||
focus:outline-none focus:ring-0 focus:shadow-none
|
||||
"
|
||||
min={options().min}
|
||||
max={options().max}
|
||||
step={options().step}
|
||||
value={props?.currentSize ? props?.currentSize : props?.defaultValue}
|
||||
id="rangeWidth"
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const Status = (props) => {
|
||||
const [circleProgressColors,setCircleProgressColors] = createStore(progressDefaultCircles)
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const { getCurrentColor,setCurrentCircleWidth } = useSettingsStorageDispatch();
|
||||
|
||||
|
||||
|
||||
const currentElement = () => settingsStorageState.selectedElementName
|
||||
const currentWidth = () => settingsStorageState.currentCircleWidth
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="p-2 flex flex-col gap-6">
|
||||
<For each={circleProgressColors}>{(progress, i) =>
|
||||
<div class="flex justify-evenly items-center">
|
||||
<h2 class="w-[100px] uppercase">{translate(progress.name,"Status")}</h2>
|
||||
<div style={"transform: scale(1.5);padding-right: 30px"}>
|
||||
<CircleProgress circleWidth={currentWidth()} showPercent={false} icon={progress.icon} progressLevel={progress.progressLevel} color={getCurrentColor(progress.name,"statusColors")} />
|
||||
</div>
|
||||
<ColorPicker isActive={currentElement() === progress.name} name={progress.name} />
|
||||
</div>
|
||||
}</For>
|
||||
<RangeSlider currentSize={currentWidth()} setSize={setCurrentCircleWidth} name={translate("circleWidth","Status")} defaultValue={2.5} options={{min: "2", max:"5", step: "0.5"}}/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,236 @@
|
||||
:root {
|
||||
--segment-color: #eee;
|
||||
--segment-progress-color: green;
|
||||
--number-color: #eee;
|
||||
--danger-color: #ff113a;
|
||||
--danger-progress-color: pink;
|
||||
--number-danger-color: #da0b64;
|
||||
--speedo-progress-color: orange;
|
||||
--damage-progress-color: #1be70d;
|
||||
--speedo-all-texts: #ff113a;
|
||||
--engine-icon-color: #fec32c;
|
||||
--tempomat-icon-color: #fec32c;
|
||||
--light-icon-color: #fec32c;
|
||||
--door-icon-color: #fec32c;
|
||||
--fuel-icon-color: white;
|
||||
--fuel-level-color: pink;
|
||||
--mileage-level-color: green;
|
||||
--unit-color: red;
|
||||
--current-speed-color: pink;
|
||||
--left-right-index-color: #00b065;
|
||||
--damage-icon-color: white;
|
||||
--speedo-background-color: rgba(0, 0, 0, 0.5);
|
||||
--speedo-outer-circle-color: #242222;
|
||||
--speedo-nooble-color: #48a3cb;
|
||||
--speedo-nooble-container: #1f2937;
|
||||
--speedo-scale-size: 0.9;
|
||||
--speedo-seatbelt-icon-color: #d22b2b;
|
||||
}
|
||||
|
||||
/* SVG DONT'T TOUCH PLEASE THANK YOU */
|
||||
.circleBackground {
|
||||
stroke: #eee;
|
||||
opacity: 0.3;
|
||||
stroke-width: 6;
|
||||
fill: transparent;
|
||||
}
|
||||
|
||||
.circleProgress {
|
||||
stroke: var(--speedo-progress-color);
|
||||
stroke-width: 6;
|
||||
stroke-dashoffset: 10;
|
||||
fill: transparent;
|
||||
}
|
||||
|
||||
/*SMALL CIRCLE SVG LEFT SIDE*/
|
||||
.backgroundPartCircle {
|
||||
stroke: #eee;
|
||||
opacity: 0.3;
|
||||
stroke-width: 4;
|
||||
fill: transparent;
|
||||
}
|
||||
|
||||
.progressPartCircle {
|
||||
stroke: var(--damage-progress-color);
|
||||
stroke-width: 4;
|
||||
/*stroke-dasharray: 0 160;*/
|
||||
fill: transparent;
|
||||
}
|
||||
|
||||
.dashesPartCircle {
|
||||
stroke: white;
|
||||
stroke-width: 4;
|
||||
stroke-dasharray: 2 34;
|
||||
stroke-dashoffset: -17;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.nob {
|
||||
width: 15px;
|
||||
height: 4px;
|
||||
background: var(--segment-color);
|
||||
}
|
||||
|
||||
.midNob {
|
||||
width: 5px;
|
||||
border-radius: 50%;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.numb {
|
||||
color: var(--number-color);
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
opacity: 0.5;
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.numb,
|
||||
.nob {
|
||||
position: absolute;
|
||||
transition: 0.5s all ease-in;
|
||||
}
|
||||
|
||||
.nob.bright {
|
||||
background: var(--segment-progress-color) !important;
|
||||
}
|
||||
.nob.brightDanger {
|
||||
background: var(--danger-progress-color) !important;
|
||||
}
|
||||
|
||||
.numb.bright {
|
||||
background: var(--segment-progress-color);
|
||||
}
|
||||
|
||||
.nob.danger {
|
||||
background: var(--danger-color);
|
||||
}
|
||||
|
||||
.numb.danger {
|
||||
color: var(--number-danger-color);
|
||||
}
|
||||
|
||||
.slideOut {
|
||||
transform: translateY(200%) scale(var(--speedo-scale-size)) !important;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
transform-origin: bottom right;
|
||||
transform: scale(var(--speedo-scale-size));
|
||||
transition: 0.5s all ease-in;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.template-main-container {
|
||||
/*top: 110px;*/
|
||||
/*left: 74%;*/
|
||||
/*position: absolute;*/
|
||||
transform: scale(0.8);
|
||||
height: 300px;
|
||||
transition: 0.5s all ease-in;
|
||||
}
|
||||
|
||||
.main-container2 {
|
||||
position: relative;
|
||||
top: 49.95%;
|
||||
left: 49.05%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: var(--speedo-background-color);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
box-shadow: inset 0 0 14px 3px #000;
|
||||
border: 5px solid var(--speedo-outer-circle-color);
|
||||
}
|
||||
|
||||
.textColor {
|
||||
color: var(--speedo-all-texts);
|
||||
}
|
||||
|
||||
.blinkerOn {
|
||||
fill-opacity: 1;
|
||||
fill: var(--left-right-index-color);
|
||||
}
|
||||
|
||||
.blink {
|
||||
transition: all 0.1s !important;
|
||||
}
|
||||
|
||||
/*SPEEDO COLORS*/
|
||||
|
||||
#fuelIcon {
|
||||
fill: var(--fuel-icon-color);
|
||||
}
|
||||
|
||||
.seatbeltIconColor {
|
||||
fill: var(--speedo-seatbelt-icon-color);
|
||||
}
|
||||
|
||||
.indexColor {
|
||||
fill: var(--left-right-index-color);
|
||||
}
|
||||
|
||||
.damageStatusIcon {
|
||||
fill: var(--damage-icon-color);
|
||||
}
|
||||
|
||||
.tempomatIcon {
|
||||
fill: var(--tempomat-icon-color);
|
||||
}
|
||||
|
||||
.doorIcon {
|
||||
fill: var(--door-icon-color);
|
||||
}
|
||||
|
||||
.lightIcon {
|
||||
stroke: var(--light-icon-color);
|
||||
}
|
||||
|
||||
.engineIcon {
|
||||
fill: var(--engine-icon-color);
|
||||
}
|
||||
|
||||
.mileageTextColor {
|
||||
color: var(--mileage-level-color);
|
||||
}
|
||||
|
||||
.unitTextColor {
|
||||
color: var(--unit-color);
|
||||
}
|
||||
|
||||
.fuelTextColor {
|
||||
color: var(--fuel-level-color);
|
||||
}
|
||||
|
||||
.currentSpeedTextColor {
|
||||
color: var(--current-speed-color);
|
||||
}
|
||||
|
||||
/*Speedo Noble*/
|
||||
|
||||
.speedoNoobleContainer {
|
||||
background: var(--speedo-nooble-container);
|
||||
}
|
||||
|
||||
.speedNobe {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transition: all 0.3s;
|
||||
height: 5px;
|
||||
left: 50%;
|
||||
top: 48%;
|
||||
transform: translate(-50%, -50%);
|
||||
transform-origin: 50% 50%;
|
||||
/* transform: rotate(-48deg); */
|
||||
}
|
||||
|
||||
.speedNobe div {
|
||||
background: var(--speedo-nooble-color);
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
width: 165px;
|
||||
left: 28px;
|
||||
border-radius: 80% 6px 6px 80%;
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
import './Speedo.css'
|
||||
import {createEffect, createSignal, onCleanup, Show} from "solid-js";
|
||||
|
||||
import Sound from '../IndicatorSound.mp3'
|
||||
import SeatbeltAlert from '../SeatbeltAlertSound.mp3';
|
||||
import SeatbeltOff from '../SeatbeltOffSound.mp3';
|
||||
import SeatbeltOn from '../SeatbeltOnSound.mp3';
|
||||
import {useHudStorageState} from "../Contexts/HudStorage";
|
||||
import {useSettingsStorageState} from "../Contexts/SettingsStorage";
|
||||
|
||||
const VehType = {
|
||||
AIR:"AIR",
|
||||
LAND:"LAND",
|
||||
MOTO: "MOTO",
|
||||
}
|
||||
|
||||
const defaultObject = {
|
||||
maxVal: 300 /**Max value of the meter*/,
|
||||
divFact: 6 /**Division value of the meter*/,
|
||||
dangerLevel: 150 /**more than this leval, color will be red*/,
|
||||
initDeg: -45 /**reading begins angle*/,
|
||||
maxDeg: 270 /**total angle of the meter reading*/,
|
||||
edgeRadius: 150 /**radius of the meter circle*/,
|
||||
indicatorRadius: 125 /**radius of indicators position*/,
|
||||
indicatorNumbRadius: 90 /**radius of numbers position*/,
|
||||
nobW: 25 /**indicator nob width*/,
|
||||
nobH: 4 /**indicator nob height*/,
|
||||
numbW: 30 /**indicator number width*/,
|
||||
numbH: 30 /**indicator number height*/,
|
||||
midNobW: 5 /**indicator mid nob width*/,
|
||||
midNobH: 3 /**indicator mid nob height*/,
|
||||
noOfSmallDiv: 5 /**no of small div between main div*/,
|
||||
}
|
||||
|
||||
/*SVGS*/
|
||||
const VehicleSpeedIndicator = (props) => <svg style="position: absolute;top: 50%;left: 50%;transform: translate(-58%, -65%);" className="absolute left-0" width="385" height="450" viewBox="0 0 350 280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill="transparent"
|
||||
class="circleBackground"
|
||||
stroke="red"
|
||||
stroke-width="15"
|
||||
d=" M 114 292 A 126 126 0 1 1 288 291"
|
||||
></path>
|
||||
|
||||
<path
|
||||
fill="transparent"
|
||||
class="circleProgress ease-in duration-100"
|
||||
stroke="red"
|
||||
stroke-width="15"
|
||||
d=" M 114 292 A 126 126 0 1 1 288 291"
|
||||
stroke-dasharray={props?.speed}
|
||||
></path>
|
||||
|
||||
{/*<path*/}
|
||||
{/* fill="transparent"*/}
|
||||
{/* class="circleDashed"*/}
|
||||
{/* stroke="red"*/}
|
||||
{/* stroke-width="15"*/}
|
||||
{/* d=" M 114 292 A 126 126 0 1 1 288 291"*/}
|
||||
{/* stroke-dasharray="18.56, 10"*/}
|
||||
{/*></path>*/}
|
||||
</svg>
|
||||
const VehicleDamageIndicator = (props) => <svg style="position: absolute;top: 50%;left: 50%;transform: translate(-64%, -66%) rotate(0deg);" className="absolute left-0" width="365" height="450" viewBox="0 0 310 280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
class="backgroundPartCircle"
|
||||
d=" M 87 282 A 140 140 0 0 1 79 130"
|
||||
fill="transparent"
|
||||
/>
|
||||
<path
|
||||
class="progressPartCircle ease-in duration-300"
|
||||
d=" M 87 282 A 140 140 0 0 1 79 130"
|
||||
fill="transparent"
|
||||
stroke-dasharray={props?.damage}
|
||||
/>
|
||||
{/*<path*/}
|
||||
{/* class="dashesPartCircle"*/}
|
||||
{/* d=" M 87 282 A 140 140 0 0 1 79 130"*/}
|
||||
{/* fill="transparent"*/}
|
||||
{/*/>*/}
|
||||
</svg>
|
||||
|
||||
/*ICONS*/
|
||||
const FuelIcon = () => <svg width="10" height="12" viewBox="0 0 10 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="fuelIcon" d="M9.92673 1.57324L8.92673 0.573233C8.82907 0.475569 8.67086 0.475569 8.57322 0.573233C8.47556 0.670896 8.47556 0.829099 8.57322 0.926739L9.39646 1.74998L8.57322 2.57322C8.52635 2.62009 8.49998 2.68356 8.49998 2.74998V3.49998C8.49998 4.05151 8.94848 4.49999 9.49998 4.49999V8.74996C9.49998 8.88789 9.38793 8.99997 9.24998 8.99997C9.11205 8.99997 8.99997 8.88792 8.99997 8.74996V8.24997C8.99997 7.8364 8.66355 7.49998 8.24997 7.49998H7.99999V1C7.99999 0.448475 7.55152 0 6.99999 0H2.00001C1.4485 0 1 0.448475 1 1V9.99998C0.448499 9.99998 0 10.4485 0 11V11.75C0 11.8882 0.11182 12 0.250007 12H8.74999C8.88817 12 8.99999 11.8882 8.99999 11.75V11C8.99999 10.4485 8.55152 9.99998 7.99999 9.99998V7.99999H8.25C8.38793 7.99999 8.5 8.11204 8.5 8.25V8.74999C8.5 9.16356 8.83643 9.49998 9.25 9.49998C9.66358 9.49998 10 9.16356 10 8.74999V1.75C9.99998 1.68358 9.97361 1.62011 9.92673 1.57324ZM6.99999 4.25462C6.99999 4.39281 6.88817 4.50463 6.74998 4.50463H2.24999C2.11181 4.50463 1.99999 4.39281 1.99999 4.25462V1.24999C1.99999 1.1118 2.11181 0.999981 2.24999 0.999981H6.74998C6.88817 0.999981 6.99999 1.1118 6.99999 1.24999V4.25462Z"/>
|
||||
</svg>
|
||||
const ArrowsIcon = (props) =>{
|
||||
|
||||
const leftIndex = () => props.state.leftIndex && props.onIndex()
|
||||
const rightIndex = () => props.state.rightIndex && props.onIndex()
|
||||
|
||||
return(
|
||||
<div class="mt-4 flex gap-4 items-center justify-center">
|
||||
<div>
|
||||
<LeftArrowIcon state={leftIndex}/>
|
||||
</div>
|
||||
<div><p class="textColor unitTextColor">{props?.kmh ? 'km/h' : 'mph'}</p></div>
|
||||
<div>
|
||||
<RightArrowIcon state={rightIndex}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const LeftArrowIcon = (props) => <svg width="19" height="20" viewBox="0 0 19 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class={` ${props?.state() ? "blinkerOn" : "" } blink indexColor`} d="M5.40816 10.5135L9.25672 4.48904C9.31624 4.39661 9.24289 4.27522 9.13217 4.28584L7.85473 4.40834C7.77375 4.4161 7.69973 4.46156 7.65617 4.52911L3.95407 10.3244C3.88993 10.4245 3.86124 10.5432 3.87259 10.6616C3.88393 10.7799 3.93467 10.8911 4.01666 10.9772L8.75246 15.9616C8.80821 16.0213 8.88937 16.0502 8.97035 16.0425L10.2478 15.92C10.3585 15.9094 10.4075 15.7762 10.3315 15.6968L5.40816 10.5135ZM10.432 10.0318L14.2806 4.0073C14.3401 3.91487 14.2667 3.79348 14.156 3.8041L12.8786 3.92659C12.7976 3.93436 12.7236 3.97982 12.68 4.04737L8.9779 9.84264C8.91376 9.94275 8.88507 10.0615 8.89641 10.1798C8.90776 10.2982 8.9585 10.4093 9.04049 10.4954L13.7763 15.4799C13.832 15.5396 13.9132 15.5685 13.9942 15.5607L15.2716 15.4382C15.3823 15.4276 15.4313 15.2945 15.3553 15.2151L10.432 10.0318Z" fill-opacity="0.3"/>
|
||||
</svg>
|
||||
const RightArrowIcon = (props) => <svg width="19" height="20" viewBox="0 0 19 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class={` ${props?.state() ? "blinkerOn" : "" } blink indexColor`} d="M13.397 10.6515L8.41209 15.7755C8.33515 15.8541 8.38249 15.9877 8.49308 15.9997L9.76897 16.1375C9.84984 16.1462 9.93152 16.1166 9.98781 16.0592L14.7831 11.1301C14.8661 11.045 14.9181 10.9345 14.9309 10.8163C14.9437 10.6981 14.9164 10.579 14.8535 10.4781L11.2207 4.64064C11.1782 4.57092 11.1045 4.52623 11.0236 4.5175L9.74776 4.37973C9.63718 4.36779 9.56238 4.48829 9.62079 4.58143L13.397 10.6515ZM8.37932 10.1097L3.39438 15.2337C3.31744 15.3123 3.36479 15.446 3.47537 15.4579L4.75126 15.5957C4.83214 15.6044 4.91381 15.5748 4.9701 15.5174L9.76534 10.5883C9.84836 10.5032 9.90042 10.3927 9.91319 10.2745C9.92595 10.1563 9.89868 10.0372 9.83574 9.93633L6.20304 4.09884C6.16047 4.02912 6.08682 3.98444 6.00594 3.9757L4.73005 3.83794C4.61947 3.826 4.54467 3.9465 4.60308 4.03963L8.37932 10.1097Z" fill-opacity="0.3"/>
|
||||
</svg>
|
||||
const VehicleDamageStatusIcon = () => <svg class="absolute bottom-[9%] left-[5%]" width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_22_147)">
|
||||
<path class="damageStatusIcon" d="M10.2982 13.8847L15.5482 19.1346L17.3944 17.2446L12.1444 11.9946L10.2982 13.8847ZM13.5532 9.33465C13.2119 9.33465 12.8444 9.2909 12.5557 9.1684L2.58941 19.0909L0.743164 17.2446L7.22691 10.7696L5.67816 9.21215L5.04816 9.82465L3.77941 8.5909V11.0934L3.16691 11.7059L0.0869141 8.5909L0.699414 7.9784H3.15816L1.93316 6.74465L5.04816 3.62965C5.29015 3.38636 5.57783 3.1933 5.89467 3.06156C6.21152 2.92982 6.55127 2.862 6.89441 2.862C7.23756 2.862 7.57731 2.92982 7.89416 3.06156C8.211 3.1933 8.49868 3.38636 8.74066 3.62965L6.89441 5.51965L8.12816 6.74465L7.50691 7.3659L9.07316 8.9234L10.6657 7.2784C10.5432 6.98965 10.4907 6.62215 10.4907 6.2984C10.4872 5.89444 10.5639 5.4938 10.7164 5.11969C10.8688 4.74558 11.094 4.40544 11.3788 4.11897C11.6637 3.8325 12.0025 3.6054 12.3758 3.45081C12.749 3.29622 13.1492 3.21723 13.5532 3.2184C14.0694 3.2184 14.5244 3.3409 14.9357 3.5859L12.5994 5.92215L13.9119 7.23465L16.2482 4.8984C16.4932 5.30965 16.6157 5.74715 16.6157 6.2984C16.6157 7.9784 15.2594 9.33465 13.5532 9.33465Z"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_22_147">
|
||||
<rect class="damageStatusIcon" width="21" height="21" transform="translate(0.0869141 0.862)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
/*MORE INDICATORS ICON*/
|
||||
const TempomatIcon = (props) => <svg class="absolute bottom-[21px] left-[111px]" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="tempomatIcon" d="M20.39 8.56001L19.15 10.42C19.7432 11.6031 20.0336 12.9148 19.9952 14.2377C19.9568 15.5606 19.5908 16.8533 18.93 18H5.06999C4.21115 16.5101 3.85528 14.7831 4.05513 13.0751C4.25497 11.367 4.9999 9.76884 6.17946 8.51744C7.35903 7.26604 8.91045 6.42805 10.6037 6.12771C12.297 5.82736 14.042 6.08064 15.58 6.85001L17.44 5.61001C15.4695 4.33293 13.1125 3.78997 10.7819 4.07628C8.45132 4.36259 6.2958 5.45991 4.69304 7.17595C3.09028 8.892 2.14252 11.1173 2.0158 13.462C1.88909 15.8067 2.59151 18.1212 3.99999 20H20C21.2266 18.3613 21.9207 16.3856 21.9887 14.3398C22.0566 12.2939 21.4951 10.2765 20.38 8.56001H20.39Z" fill-opacity={props?.state ? '1' : '0.5'}/>
|
||||
<path class="tempomatIcon" d="M10.59 15.41C10.7757 15.5959 10.9963 15.7435 11.2391 15.8441C11.4819 15.9448 11.7422 15.9966 12.005 15.9966C12.2678 15.9966 12.5281 15.9448 12.7709 15.8441C13.0137 15.7435 13.2342 15.5959 13.42 15.41L19.08 6.91998L10.59 12.58C10.404 12.7657 10.2565 12.9863 10.1559 13.2291C10.0552 13.4719 10.0034 13.7322 10.0034 13.995C10.0034 14.2578 10.0552 14.5181 10.1559 14.7609C10.2565 15.0037 10.404 15.2242 10.59 15.41Z" fill-opacity={props?.state ? '1' : '0.5'}/>
|
||||
</svg>
|
||||
const DoorIcon = (props) =><svg class="absolute right-[73px] bottom-[37px]" width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="doorIcon" d="M19.0869 14.862H16.0869V16.862H19.0869V14.862ZM22.0869 21.862H3.08691V11.862L11.0869 3.862H21.0869C21.3521 3.862 21.6065 3.96736 21.794 4.15489C21.9816 4.34243 22.0869 4.59678 22.0869 4.862V21.862ZM11.9169 5.862L5.91691 11.862H20.0869V5.862H11.9169Z" fill-opacity={props?.state ? '1' : '0.5'}/>
|
||||
</svg>
|
||||
const LightIcon = (props) => <svg class={`absolute ${props?.vehType ? 'right-[111px] bottom-[21px]' :'right-[138px] bottom-[22px]'}`} width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="lightIcon" d="M10.0869 22.862H14.0869H10.0869ZM5.08692 9.862C5.08692 8.00548 5.82441 6.22501 7.13717 4.91225C8.44992 3.5995 10.2304 2.862 12.0869 2.862C13.9434 2.862 15.7239 3.5995 17.0367 4.91225C18.3494 6.22501 19.0869 8.00548 19.0869 9.862C19.0876 10.9891 18.815 12.0995 18.2925 13.0982C17.77 14.0968 17.0132 14.9539 16.0869 15.596L15.5449 18.162C15.4732 18.635 15.2342 19.0666 14.8715 19.3785C14.5088 19.6904 14.0463 19.8619 13.5679 19.862H10.6059C10.1275 19.8619 9.66503 19.6904 9.30231 19.3785C8.93958 19.0666 8.70067 18.635 8.62892 18.162L8.08692 15.607C7.16032 14.9626 6.40349 14.1035 5.88107 13.1031C5.35865 12.1027 5.08617 10.9906 5.08692 9.862V9.862Z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-opacity={props?.state ? '1' : '0.5'}/>
|
||||
<path class="lightIcon" d="M8.08691 15.862H16.0869" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-opacity={props?.state ? '1' : '0.5'}/>
|
||||
</svg>
|
||||
const EngineIcon = (props) =><svg class="absolute left-[67px] bottom-[34px]" width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class="engineIcon" d="M7.08691 4.862V6.862H10.0869V8.862H7.08691L5.08691 10.862V13.862H3.08691V10.862H1.08691V18.862H3.08691V15.862H5.08691V18.862H8.08691L10.0869 20.862H18.0869V16.862H20.0869V19.862H23.0869V9.862H20.0869V12.862H18.0869V8.862H12.0869V6.862H15.0869V4.862H7.08691Z" fill-opacity={props?.state ? '1' : '0.5'}/>
|
||||
</svg>
|
||||
const SeatbeltIcon = (props) => <svg width="45" height="45" viewBox="0 0 13 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path class={` ${props?.state() ? "blinkerOn" : "" } blink seatbeltIconColor`} d="M6.4623 0C6.86228 0 7.24587 0.158891 7.5287 0.441718C7.81153 0.724546 7.97042 1.10814 7.97042 1.50812C7.97042 2.34513 7.2993 3.01624 6.4623 3.01624C6.06232 3.01624 5.67872 2.85735 5.39589 2.57452C5.11307 2.2917 4.95418 1.9081 4.95418 1.50812C4.95418 1.10814 5.11307 0.724546 5.39589 0.441718C5.67872 0.158891 6.06232 0 6.4623 0ZM6.75638 9.64443C7.82752 9.64026 8.89787 9.70322 9.96114 9.83295C10.0064 7.7819 9.82541 5.97216 9.47854 5.27842C9.38051 5.07483 9.24478 4.90139 9.10151 4.75058L3.01624 9.96868C4.04176 9.80278 5.33121 9.64443 6.75638 9.64443ZM3.03886 11.3109C3.13689 12.623 3.33295 13.9501 3.64965 15.0812H5.21056C4.99188 14.4176 4.83353 13.641 4.71288 12.819C4.71288 12.819 6.4623 12.4872 8.21172 12.819C8.09107 13.641 7.93271 14.4176 7.71404 15.0812H9.27494C9.60673 13.9124 9.80278 12.5249 9.90081 11.1526C8.85742 11.0264 7.80737 10.9635 6.75638 10.964C5.30104 10.964 4.03422 11.1224 3.03886 11.3109ZM6.4623 3.7703C6.4623 3.7703 4.20012 3.7703 3.44606 5.27842C3.18967 5.79118 3.02378 6.89965 2.971 8.2645L7.91009 4.02668C7.16357 3.7703 6.4623 3.7703 6.4623 3.7703ZM11.4165 2.7674L10.5568 1.7645L7.91009 4.03422C8.32483 4.17749 8.76218 4.40371 9.10151 4.75058L11.4165 2.7674ZM13 10.4287C12.9321 10.406 11.8463 10.0516 9.96114 9.83295C9.9536 10.2628 9.93097 10.7077 9.90081 11.1526C11.5974 11.3637 12.5702 11.6879 12.5853 11.6879L13 10.4287ZM2.971 8.2645L0 10.8132L0.671114 11.9292C0.686195 11.9217 1.5609 11.5824 3.03886 11.3109C2.95592 10.2477 2.93329 9.19954 2.971 8.2645Z" fill-opacity="0.3"/>
|
||||
</svg>
|
||||
|
||||
|
||||
export const Speedo = (props) =>{
|
||||
|
||||
const hudStorageState = useHudStorageState();
|
||||
const settingsStorageState = useSettingsStorageState();
|
||||
const settings = () => settingsStorageState.settings
|
||||
const defaultConfigs = () => settingsStorageState.defaultConfigs
|
||||
const [checkSound, setCheckSound] = createSignal(false)
|
||||
const [onIndex,setOnIndex] = createSignal(false)
|
||||
const [seatbeltState, setSeatbeltState] = createSignal(false)
|
||||
const speedo = () => hudStorageState.speedo
|
||||
const indicators = () => speedo().defaultIndicators
|
||||
const damage = () => speedo().damageLevel
|
||||
const vehType = () => speedo().vehType
|
||||
const isKmh = () => defaultConfigs().Kmh
|
||||
const speed = () => speedo().speed
|
||||
const show = () => speedo().show
|
||||
const fuel = () => speedo().fuel
|
||||
const mileage = () => speedo().mileage
|
||||
const isDriver = () => speedo().driver
|
||||
const rpm = () => speedo().rpm
|
||||
|
||||
let rows = []
|
||||
const createTemplate = () =>{
|
||||
defaultObject.maxVal = isKmh() ? 300 : 200
|
||||
defaultObject.divFact = isKmh() ? 6 : 4
|
||||
defaultObject.dangerLevel = isKmh() ? 180 : 120
|
||||
|
||||
if(vehType() === VehType.AIR){
|
||||
defaultObject.maxVal = 2500
|
||||
defaultObject.divFact = 50
|
||||
defaultObject.dangerLevel = 1500
|
||||
}
|
||||
|
||||
|
||||
if(!props?.template){
|
||||
const speedoContainer = document.getElementById('speedoContainer');
|
||||
if(speedoContainer){
|
||||
speedoContainer.innerHTML = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const noOfDev = defaultObject.maxVal/ defaultObject.divFact
|
||||
const divDeg = defaultObject.maxDeg/noOfDev
|
||||
let induCatorLinesPosLeft ,induCatorLinesPosTop,tempDiv,induCatorNumbPosLeft,induCatorNumbPosTop = ''
|
||||
|
||||
if(!settings().Needle && vehType() !== VehType.AIR){
|
||||
rows.push(<div class="speedNobe">
|
||||
<div></div>
|
||||
</div>)
|
||||
}
|
||||
|
||||
let tempDegInd
|
||||
for(let i = 0; i <= noOfDev; i++){
|
||||
|
||||
const curDig = defaultObject.initDeg + i * divDeg
|
||||
let curIndVal = i * defaultObject.divFact;
|
||||
|
||||
let dangCls = "";
|
||||
if (curIndVal >= defaultObject.dangerLevel) {
|
||||
dangCls = "danger";
|
||||
}
|
||||
|
||||
let induCatorLinesPosY =
|
||||
defaultObject.indicatorRadius * Math.cos(0.01746 * curDig);
|
||||
let induCatorLinesPosX =
|
||||
defaultObject.indicatorRadius * Math.sin(0.01746 * curDig);
|
||||
|
||||
let induCatorNumbPosY =
|
||||
defaultObject.indicatorNumbRadius * Math.cos(0.01746 * curDig);
|
||||
let induCatorNumbPosX =
|
||||
defaultObject.indicatorNumbRadius * Math.sin(0.01746 * curDig);
|
||||
|
||||
if (i % defaultObject.noOfSmallDiv === 0) {
|
||||
induCatorLinesPosLeft =
|
||||
defaultObject.edgeRadius - induCatorLinesPosX - 2;
|
||||
induCatorLinesPosTop =
|
||||
defaultObject.edgeRadius - induCatorLinesPosY - 10;
|
||||
|
||||
tempDegInd = `transform: rotate(${curDig}deg)`
|
||||
|
||||
|
||||
|
||||
induCatorNumbPosLeft =
|
||||
defaultObject.edgeRadius -
|
||||
induCatorNumbPosX -
|
||||
defaultObject.numbW / 2;
|
||||
induCatorNumbPosTop =
|
||||
defaultObject.edgeRadius -
|
||||
induCatorNumbPosY -
|
||||
defaultObject.numbH / 2;
|
||||
|
||||
rows.push(
|
||||
<>
|
||||
<div class={`nob ${dangCls}`} style={`left: ${induCatorLinesPosTop}px; top: ${induCatorLinesPosLeft}px; ${tempDegInd}`}>
|
||||
|
||||
</div>
|
||||
<div class={`numb ${dangCls}`} style={`left: ${induCatorNumbPosTop}px; top: ${induCatorNumbPosLeft}px;`}>
|
||||
{curIndVal}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
induCatorLinesPosLeft =
|
||||
defaultObject.edgeRadius -
|
||||
induCatorLinesPosX -
|
||||
defaultObject.midNobH / 2;
|
||||
induCatorLinesPosTop =
|
||||
defaultObject.edgeRadius -
|
||||
induCatorLinesPosY -
|
||||
defaultObject.midNobW / 2;
|
||||
|
||||
tempDegInd = `transform: rotate(${curDig}deg)`
|
||||
|
||||
|
||||
rows.push(
|
||||
<>
|
||||
<div class={`nob midNob ${dangCls}`} style={`left: ${induCatorLinesPosTop}px; top: ${induCatorLinesPosLeft}px; ${tempDegInd}`}>
|
||||
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
const IndicatorSound = new Audio(Sound);
|
||||
const SeatbeltAlertSound = new Audio(SeatbeltAlert)
|
||||
const SeatbeltOnSound = new Audio(SeatbeltOn)
|
||||
const SeatbeltOffSound = new Audio(SeatbeltOff)
|
||||
SeatbeltOnSound.volume = 0.5
|
||||
SeatbeltOffSound.volume = 0.5
|
||||
SeatbeltAlertSound.volume = 0.2
|
||||
IndicatorSound.volume = 0.2
|
||||
const indexTimer = setInterval(()=>{
|
||||
if((indicators().leftIndex || indicators().rightIndex)){
|
||||
if(!settings().IndicatorSound && show()){
|
||||
if(!props?.template){
|
||||
IndicatorSound.play();
|
||||
}
|
||||
}
|
||||
setOnIndex(onIndex => !onIndex)
|
||||
}
|
||||
if(!indicators().seatbelt && vehType() !== VehType.MOTO){
|
||||
if(!settings().IndicatorSeatbeltSound && show()){
|
||||
if(!props?.template && !checkSound()){
|
||||
SeatbeltAlertSound.play();
|
||||
}
|
||||
}
|
||||
setSeatbeltState(seatbeltState => !seatbeltState)
|
||||
}
|
||||
},500)
|
||||
onCleanup(() => clearInterval(indexTimer));
|
||||
|
||||
createEffect(()=>{
|
||||
const allElements = document.getElementsByClassName('nob')
|
||||
const elements = document.querySelectorAll('#speedoContainer .nob');
|
||||
const elementsTemplate = document.querySelectorAll('#templateSpeedoContainer .nob');
|
||||
const currentSpeed = VehType.AIR !== vehType() ? speed() : rpm()
|
||||
|
||||
if(!settings().IndicatorSeatbeltSound){
|
||||
if(indicators().seatbelt && !checkSound()){
|
||||
if(!checkSound()){
|
||||
SeatbeltOnSound.play();
|
||||
setCheckSound(true)
|
||||
}
|
||||
}
|
||||
|
||||
if(checkSound() && !indicators().seatbelt){
|
||||
SeatbeltOffSound.play();
|
||||
setCheckSound(false)
|
||||
}
|
||||
}
|
||||
|
||||
if(!settings().Needle){
|
||||
const speedNoble = document.querySelectorAll('#speedoContainer .speedNobe')
|
||||
if(speedNoble.length > 0){
|
||||
const speedInDeg = (266/defaultObject.maxVal) * currentSpeed + defaultObject.initDeg;
|
||||
speedNoble[0].style.transform = `translate(-50%, -50%) rotate(${speedInDeg}deg)`
|
||||
}
|
||||
}
|
||||
|
||||
allElements.forEach((element)=>{
|
||||
element.classList.remove("bright");
|
||||
element.classList.remove("brightDanger")
|
||||
})
|
||||
|
||||
for(let i = 0; i < elements.length; i++){
|
||||
const calcDeg = i * defaultObject.divFact
|
||||
if(currentSpeed < calcDeg){
|
||||
break
|
||||
}
|
||||
if(calcDeg >= defaultObject.dangerLevel){
|
||||
elements[i].classList.add("brightDanger");
|
||||
if(elementsTemplate.length > 0)
|
||||
elementsTemplate[i].classList.add("brightDanger");
|
||||
}
|
||||
else{
|
||||
elements[i].classList.add("bright");
|
||||
if(elementsTemplate.length > 0)
|
||||
elementsTemplate[i].classList.add("bright")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/* HUD COMPONENTS */
|
||||
const VehicleHud = () =>{
|
||||
return(
|
||||
<>
|
||||
<VehicleSpeedIndicator speed={speedo().speedInDeg}/>
|
||||
<VehicleDamageIndicator damage={damage()}/>
|
||||
<VehicleDamageStatusIcon/>
|
||||
<TempomatIcon state={indicators()?.tempomat}/>
|
||||
<DoorIcon state={indicators()?.door}/>
|
||||
<LightIcon state={indicators()?.light} vehType={vehType() !== VehType.AIR}/>
|
||||
<EngineIcon state={indicators()?.engine}/>
|
||||
<Show when={!settings().Needle} keyed>
|
||||
<div class="speedoNoobleContainer absolute z-10 rounded-full w-10 h-10 top-1/2 left-1/2 -translate-x-1/2 -translate-y-[70%]"></div>
|
||||
</Show>
|
||||
<Show when={settings().Needle} keyed>
|
||||
<h2 class="text-5xl z-20 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 textColor currentSpeedTextColor">{speed()}</h2>
|
||||
</Show>
|
||||
<div class="absolute w-[30%] top-1/2 left-1/2 -translate-x-1/2 translate-y-[15%]">
|
||||
<div class="flex flex-col">
|
||||
<ArrowsIcon state={indicators()} onIndex={onIndex} kmh={isKmh()}/>
|
||||
<div>
|
||||
<Show when={props?.template || isDriver()} keyed>
|
||||
<span class="textColor mileageTextColor">{mileage()}{isKmh() ? 'km' : 'mi'}</span>
|
||||
</Show>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<div class="textColor fuelTextColor">{fuel().level}/{fuel().maxLevel}</div>
|
||||
<div>
|
||||
<FuelIcon/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
const AirHud = () =>{
|
||||
return(
|
||||
<>
|
||||
<VehicleDamageIndicator damage={damage()}/>
|
||||
<VehicleDamageStatusIcon/>
|
||||
<DoorIcon state={indicators()?.door}/>
|
||||
<LightIcon state={indicators()?.light} vehType={vehType() !== VehType.AIR}/>
|
||||
<EngineIcon state={indicators()?.engine}/>
|
||||
<h2 class="text-5xl absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-[70%] textColor currentSpeedTextColor">{speed()}</h2>
|
||||
<div class="absolute w-[30%] top-1/2 left-1/2 -translate-x-1/2 translate-y-[15%]">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col mt-2 items-center justify-center">
|
||||
<div class="textColor fuelTextColor">{fuel().level}/{fuel().maxLevel}</div>
|
||||
<div>
|
||||
<FuelIcon/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return(
|
||||
<div class={`${props?.template ? 'template-main-container' : 'speedo main-container'} ${!show() && !props?.template ? 'slideOut' : ''}`}>
|
||||
|
||||
<Show when={!indicators().seatbelt && vehType() !== VehType.MOTO} keyed>
|
||||
<div class="w-10 h-10 absolute top-[26%] -left-[25%]">
|
||||
<SeatbeltIcon state={seatbeltState}/>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<div class="main-container2"></div>
|
||||
|
||||
<Show when={vehType() === VehType.AIR} keyed>
|
||||
<AirHud/>
|
||||
</Show>
|
||||
|
||||
<Show when={vehType() !== VehType.AIR} keyed>
|
||||
<VehicleHud/>
|
||||
</Show>
|
||||
|
||||
<div class="w-[300px] h-[300px]" id={props?.template ? 'templateSpeedoContainer': 'speedoContainer'}>
|
||||
{createTemplate()}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
import {createContext, onMount, useContext} from "solid-js";
|
||||
import {createStore, produce} from "solid-js/store";
|
||||
import {ArmorIcon, DrinkIcon, FoodIcon, HealthIcon, OxygenIcon, StaminaIcon} from "../Icons";
|
||||
|
||||
const StateContext = createContext()
|
||||
const DispatchContext = createContext()
|
||||
|
||||
const initialState = {
|
||||
status:[
|
||||
{
|
||||
name: "healthBar",
|
||||
progressLevel: 50,
|
||||
color: "red",
|
||||
icon: HealthIcon
|
||||
},
|
||||
{
|
||||
name: "armorBar",
|
||||
progressLevel: 100,
|
||||
color: "blue",
|
||||
icon: ArmorIcon
|
||||
},
|
||||
{
|
||||
name: "drinkBar",
|
||||
progressLevel: 100,
|
||||
color: "lightblue",
|
||||
icon: DrinkIcon
|
||||
},
|
||||
{
|
||||
name: "foodBar",
|
||||
progressLevel: 100,
|
||||
color: "yellow",
|
||||
icon: FoodIcon
|
||||
},
|
||||
{
|
||||
name: "oxygenBar",
|
||||
progressLevel: 100,
|
||||
color: "pink",
|
||||
icon: OxygenIcon
|
||||
},
|
||||
{
|
||||
name: "staminaBar",
|
||||
progressLevel: 100,
|
||||
color: "green",
|
||||
icon: StaminaIcon
|
||||
}
|
||||
],
|
||||
speedo:{
|
||||
show: false,
|
||||
fuel: {level: 50, maxLevel: 100},
|
||||
mileage: 5000,
|
||||
kmh: false,
|
||||
speed: 0,
|
||||
rpm: 100,
|
||||
damage: 100,
|
||||
vehType: "LAND",
|
||||
driver: false,
|
||||
defaultIndicators: {
|
||||
seatbelt: false,
|
||||
tempomat: true,
|
||||
door: false,
|
||||
light: false,
|
||||
engine: false,
|
||||
leftIndex: false,
|
||||
rightIndex: false
|
||||
}
|
||||
},
|
||||
hud:{
|
||||
playerId: 1,
|
||||
onlinePlayers:150,
|
||||
serverLogo: "https://esx.s3.fr-par.scw.cloud/blanc-800x800.png",
|
||||
moneys: { bank: 75000, money: 100000 },
|
||||
job: "",
|
||||
weaponData: { use: true ,image: "pistol", name: "WEAPON NAME" , currentAmmo: 32, maxAmmo: 128 , isWeaponMelee: true},
|
||||
streetName: "",
|
||||
voice: {mic:false, radio:false, range: 2}
|
||||
},
|
||||
}
|
||||
export default function HudStorageProvider(props){
|
||||
const [store, setStore] = createStore(initialState)
|
||||
|
||||
function updateStatus(newValues){
|
||||
store.status.forEach((currentStatus)=>{
|
||||
setStore(
|
||||
"status",
|
||||
currentData => currentData.name === currentStatus.name,
|
||||
produce((currentData) => (currentData.progressLevel = newValues[currentStatus.name] !== undefined ? newValues[currentStatus.name] : currentData.progressLevel)),
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
function updateSpeedo(newValues){
|
||||
newValues.speedInDeg = getSpeedInDeg()
|
||||
newValues.damageLevel = getDamageLevel()
|
||||
setStore("speedo",{
|
||||
...newValues,
|
||||
fuel: {...newValues.fuel},
|
||||
defaultIndicators: {...newValues.defaultIndicators}
|
||||
});
|
||||
}
|
||||
|
||||
//!!Figyelni kell a nested object-re mert nem fog frissülni a store
|
||||
function updateHud(newValues){
|
||||
setStore("hud",{
|
||||
...newValues,
|
||||
moneys: {...newValues.moneys},
|
||||
weaponData: {...newValues.weaponData},
|
||||
voice: {...newValues.voice}
|
||||
})
|
||||
}
|
||||
|
||||
/*SpeedoTemplate functions*/
|
||||
function getSpeedInDeg(){
|
||||
const speedInDeg = (600/50) * store.speedo.rpm/10
|
||||
|
||||
return `${speedInDeg+9} 610`
|
||||
}
|
||||
|
||||
function getDamageLevel(){
|
||||
return `${store.speedo.damage * 1.6} 160`
|
||||
}
|
||||
|
||||
/*Voice functions*/
|
||||
function changeVoiceRange(newRange){
|
||||
setStore(
|
||||
"hud",
|
||||
produce((currentData) => (currentData.voice.range = newRange)),
|
||||
);
|
||||
}
|
||||
|
||||
function currentMicRangeStatus(){
|
||||
let micStatus = store.hud.voice.range && (store.hud.voice.range > 0) && (store.hud.voice.range < 4) ? store.hud.voice.range : 2
|
||||
|
||||
let micDefaultRange = Array(micStatus).fill(true)
|
||||
micDefaultRange.push(...Array(3-micStatus).fill(false))
|
||||
|
||||
return micDefaultRange
|
||||
}
|
||||
|
||||
|
||||
return(
|
||||
<StateContext.Provider value={store}>
|
||||
<DispatchContext.Provider value={{
|
||||
updateStatus,
|
||||
updateSpeedo,
|
||||
updateHud,
|
||||
getSpeedInDeg,
|
||||
getDamageLevel,
|
||||
changeVoiceRange,
|
||||
currentMicRangeStatus
|
||||
}}>
|
||||
{props.children}
|
||||
</DispatchContext.Provider>
|
||||
</StateContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useHudStorageState = () => useContext(StateContext)
|
||||
export const useHudStorageDispatch = () => useContext(DispatchContext)
|
||||
@@ -0,0 +1,465 @@
|
||||
import {createContext, onMount, useContext} from "solid-js";
|
||||
import {createStore, produce} from "solid-js/store";
|
||||
import {disableDefaultConfig, progressDefaultCircles, speedoDefaultColors} from "../../../DefaultDatas";
|
||||
import {Nui} from "../../Utils/Nui";
|
||||
|
||||
const StateContext = createContext()
|
||||
const DispatchContext = createContext()
|
||||
|
||||
const initialState = {
|
||||
statusColors:[
|
||||
{
|
||||
name: "healthBar",
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
name: "armorBar",
|
||||
color: "blue"
|
||||
},
|
||||
{
|
||||
name: "drinkBar",
|
||||
color: "lightblue"
|
||||
},
|
||||
{
|
||||
name: "foodBar",
|
||||
color: "yellow"
|
||||
},
|
||||
{
|
||||
name: "oxygenBar",
|
||||
color: "pink"
|
||||
},
|
||||
{
|
||||
name: "staminaBar",
|
||||
color: "green"
|
||||
}
|
||||
],
|
||||
infoColors: [
|
||||
{
|
||||
name: "money-text-color",
|
||||
color: "blue"
|
||||
},
|
||||
{
|
||||
name: "bank-text-color",
|
||||
color: "orange"
|
||||
},
|
||||
{
|
||||
name: "job-text-color",
|
||||
color: "red"
|
||||
}
|
||||
],
|
||||
speedoColors:[
|
||||
{
|
||||
name: "segment-color",
|
||||
color: "#eee"
|
||||
},
|
||||
{
|
||||
name:"segment-progress-color",
|
||||
color:"green"
|
||||
},
|
||||
{
|
||||
name: "number-color",
|
||||
color: "#eee"
|
||||
},
|
||||
{
|
||||
name: "danger-color",
|
||||
color: "#ff113a"
|
||||
},
|
||||
{
|
||||
name:"danger-progress-color",
|
||||
color:"pink"
|
||||
},
|
||||
{
|
||||
name: "number-danger-color",
|
||||
color: "#da0b64"
|
||||
},
|
||||
{
|
||||
name: "speedo-progress-color",
|
||||
color: "orange"
|
||||
},
|
||||
{
|
||||
name: "damage-progress-color",
|
||||
color: "#1be70d"
|
||||
},
|
||||
{
|
||||
name: "engine-icon-color",
|
||||
color: "#FEC32C"
|
||||
},
|
||||
|
||||
{
|
||||
name: "tempomat-icon-color",
|
||||
color: "#FEC32C"
|
||||
},
|
||||
{
|
||||
name: "light-icon-color",
|
||||
color: "#FEC32C"
|
||||
},
|
||||
{
|
||||
name: "door-icon-color",
|
||||
color: "#FEC32C"
|
||||
},
|
||||
{
|
||||
name: "fuel-icon-color",
|
||||
color: "white"
|
||||
},
|
||||
{
|
||||
name: "fuel-level-color",
|
||||
color: "pink"
|
||||
},
|
||||
{
|
||||
name: "mileage-level-color",
|
||||
color: "green"
|
||||
},
|
||||
{
|
||||
name: "unit-color",
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
name: "current-speed-color",
|
||||
color: "pink"
|
||||
},
|
||||
{
|
||||
name: "left-right-index-color",
|
||||
color: "#00B065"
|
||||
},
|
||||
{
|
||||
name: "damage-icon-color",
|
||||
color: "white"
|
||||
},
|
||||
{
|
||||
name: "speedo-background-color",
|
||||
color: "rgba(0,0,0,.5)"
|
||||
},
|
||||
{
|
||||
name: "speedo-outer-circle-color",
|
||||
color: "#242222"
|
||||
},
|
||||
{
|
||||
name: "speedo-nooble-color",
|
||||
color: "#48a3cb"
|
||||
},
|
||||
{
|
||||
name: "speedo-nooble-container",
|
||||
color: "#1f2937"
|
||||
},
|
||||
{
|
||||
name: "speedo-seatbelt-icon-color",
|
||||
color: "#D22B2B"
|
||||
}
|
||||
],
|
||||
settings:{
|
||||
Status: false,
|
||||
Vehicle: false,
|
||||
Weapon: false,
|
||||
Position: false,
|
||||
Voice: false,
|
||||
Money: false,
|
||||
Info: false,
|
||||
IndicatorSound: false,
|
||||
IndicatorSeatbeltSound: false,
|
||||
VehicleHandlers:false,
|
||||
MinimapOnFoot:false,
|
||||
Needle: false,
|
||||
Kmh: true,
|
||||
StatusPercent:false,
|
||||
CenterStatuses:false
|
||||
},
|
||||
disableDefaultConfig:{
|
||||
Status: false,
|
||||
Vehicle: false,
|
||||
Weapon: false,
|
||||
Position: false,
|
||||
Voice: false,
|
||||
Money: false,
|
||||
Info: false,
|
||||
IndicatorSound: false,
|
||||
IndicatorSeatbeltSound: false,
|
||||
VehicleHandlers:false,
|
||||
MinimapOnFoot:false,
|
||||
Needle:false,
|
||||
Kmh: true,
|
||||
StatusPercent:false,
|
||||
CenterStatuses:false
|
||||
},
|
||||
pickedColor: "",
|
||||
currentCircleWidth: "",
|
||||
currentSpeedoSize: "",
|
||||
selectedElementName: "",
|
||||
selectedMenuName: "",
|
||||
showPanel: false,
|
||||
defaultConfigs:{
|
||||
ServerLogo: "",
|
||||
Kmh: true
|
||||
}
|
||||
}
|
||||
|
||||
export default function SettingsStorage(props){
|
||||
const [store,setStore] = createStore(initialState)
|
||||
|
||||
/**
|
||||
* Init load check if exist localstorage load saved values
|
||||
*/
|
||||
onMount(()=>{
|
||||
const datas = ["statusColors","speedoColors","settings", "currentCircleWidth", "currentSpeedoSize"]
|
||||
datas.forEach((dataKey)=>{
|
||||
let currentData = handleLocalStorage(dataKey,"get")
|
||||
if(!currentData){
|
||||
return
|
||||
}
|
||||
setStore(dataKey, currentData)
|
||||
|
||||
if(dataKey === "speedoColors"){
|
||||
changeThemeColors(currentData)
|
||||
}
|
||||
|
||||
if(dataKey === "currentSpeedoSize"){
|
||||
setCurrentSpeedoSize(currentData)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Set current selected menu name
|
||||
* @param currentMenuName current selected menu name
|
||||
*/
|
||||
function setSelectedMenu(currentMenuName){
|
||||
setStore("selectedMenuName",currentMenuName)
|
||||
}
|
||||
|
||||
/*COLOR PICKER FUNCTIONS*/
|
||||
|
||||
/**
|
||||
* Set current picked color in colorpicker
|
||||
* @param newColor picked color
|
||||
*/
|
||||
function setCurrentPickedColor(newColor){
|
||||
setStore("pickedColor", newColor)
|
||||
updateColors()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current width value in range slider
|
||||
* @param newWidth current width value
|
||||
*/
|
||||
function setCurrentCircleWidth(newWidth){
|
||||
setStore("currentCircleWidth", newWidth)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current size value in range slider
|
||||
* @param newWidth current width value
|
||||
*/
|
||||
function setCurrentSpeedoSize(newSize){
|
||||
setStore("currentSpeedoSize", newSize)
|
||||
const r = document.querySelector(':root');
|
||||
r.style.setProperty('--speedo-scale-size', newSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current selected element name
|
||||
* @param selectedName current selected element name
|
||||
*/
|
||||
function setSelectedElement(selectedName){
|
||||
setStore("selectedElementName", selectedName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle update colors by current selected menu name
|
||||
*/
|
||||
function updateColors(){
|
||||
const currentSelectedMenu = store.selectedMenuName ? store.selectedMenuName.toLowerCase() : 'status'
|
||||
const currentPickedColor = store.pickedColor
|
||||
const currentSelectedCircleName = store.selectedElementName
|
||||
setStore(
|
||||
`${currentSelectedMenu}Colors`,
|
||||
currentStatus => currentStatus.name === currentSelectedCircleName,
|
||||
produce((currentStatus) => (currentStatus.color = currentPickedColor)),
|
||||
);
|
||||
|
||||
if(currentSelectedMenu === "speedo"){
|
||||
changeThemeColors(store.speedoColors)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get current element color in current store
|
||||
* */
|
||||
function getCurrentColor(editElementName,currentStoreName){
|
||||
const currentStore = store[currentStoreName]
|
||||
return currentStore?.find((data) => data.name === editElementName).color
|
||||
}
|
||||
|
||||
/**
|
||||
* Set param colors :root stlye in css
|
||||
* Handle array and objects
|
||||
* @param colors current default colors array
|
||||
*/
|
||||
function changeThemeColors(colors){
|
||||
const r = document.querySelector(':root');
|
||||
if(Array.isArray(colors)){
|
||||
colors.forEach((color)=>{
|
||||
r.style.setProperty(`--${color.name}`,color.color)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
Object.keys(colors).forEach((color)=>{
|
||||
r.style.setProperty(`--${color}`,colors[color])
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset all colors and remove localstore key by current selected menu name
|
||||
* */
|
||||
function resetColors(){
|
||||
const currentSelectedMenu = store.selectedMenuName ? store.selectedMenuName.toLowerCase() : 'status'
|
||||
const selectMenu = `${currentSelectedMenu}Colors`
|
||||
let defaultData = progressDefaultCircles
|
||||
if(currentSelectedMenu === "speedo"){
|
||||
changeThemeColors(speedoDefaultColors)
|
||||
defaultData = speedoDefaultColors
|
||||
handleLocalStorage("currentSpeedoSize","remove")
|
||||
setCurrentSpeedoSize(0.9)
|
||||
}
|
||||
|
||||
defaultData.forEach((data)=>{
|
||||
setStore(
|
||||
selectMenu,
|
||||
currentData => currentData.name === data.name,
|
||||
produce((currentData) => (currentData.color = data.color)),
|
||||
);
|
||||
})
|
||||
|
||||
handleLocalStorage(selectMenu,"remove")
|
||||
if(currentSelectedMenu === "status"){
|
||||
handleLocalStorage("currentCircleWidth","remove")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save colors and localstorage key by current selected menu name
|
||||
*/
|
||||
function saveColors(){
|
||||
const currentSelectedMenu = store.selectedMenuName ? store.selectedMenuName.toLowerCase() : 'status'
|
||||
|
||||
const selectMenu = `${currentSelectedMenu}Colors`
|
||||
const newColors = store[selectMenu].map((data) => {
|
||||
return {name: data.name, color: data.color}
|
||||
})
|
||||
|
||||
if(currentSelectedMenu === "status"){
|
||||
handleLocalStorage("currentCircleWidth","add",store.currentCircleWidth)
|
||||
}
|
||||
handleLocalStorage("currentSpeedoSize","add",store.currentSpeedoSize)
|
||||
handleLocalStorage(selectMenu,"add",newColors)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle local storage
|
||||
* @param key current setted key
|
||||
* @param type add/remove
|
||||
* @param newData if add you can use pass new save data
|
||||
*/
|
||||
function handleLocalStorage(key,type = "add", newData = ""){
|
||||
if(type === "remove"){
|
||||
if(localStorage.hasOwnProperty(key)){
|
||||
localStorage.removeItem(key)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if(type === "get"){
|
||||
if(localStorage.hasOwnProperty(key)){
|
||||
return JSON.parse(localStorage.getItem(key))
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
localStorage.setItem(key,JSON.stringify(newData))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set settings in store by name
|
||||
* @param settingsName current settings name
|
||||
* @param settingsValue current settings value
|
||||
* @param storeKey current update store name
|
||||
*/
|
||||
function setSettingsByName(settingsName,settingsValue, storeKey = "settings"){
|
||||
if(settingsValue !== undefined){
|
||||
setStore(storeKey,
|
||||
produce((data) => {
|
||||
data[settingsName] = settingsValue
|
||||
}))
|
||||
return
|
||||
}
|
||||
setStore("settings",
|
||||
produce((data) => {
|
||||
data[settingsName] = !data[settingsName]
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings in localstorage
|
||||
*/
|
||||
function saveSettings(){
|
||||
const newSettings = store.settings
|
||||
if(!newSettings){
|
||||
return
|
||||
}
|
||||
handleLocalStorage("settings","add",newSettings)
|
||||
Nui.send("notify",{state: "save"})
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset settings in localstorage(remove by settings key)
|
||||
*/
|
||||
function resetSettings(){
|
||||
setStore("settings", store.disableDefaultConfig)
|
||||
handleLocalStorage("settings","remove")
|
||||
Nui.send("notify",{state: "reset"})
|
||||
}
|
||||
|
||||
function toggleShowPanel(){
|
||||
setStore("showPanel", !store.showPanel)
|
||||
}
|
||||
|
||||
function setDefaultConfigs(newConfig) {
|
||||
changeThemeColors(newConfig["Colors"]["Info"])
|
||||
setSettingsByName("Kmh", newConfig["Default"].Kmh)
|
||||
setStore("defaultConfigs",newConfig["Default"])
|
||||
setStore("disableDefaultConfig",newConfig["Disable"])
|
||||
if(!handleLocalStorage("settings","get")){
|
||||
setStore("settings",newConfig["Disable"])
|
||||
}
|
||||
}
|
||||
|
||||
return(
|
||||
<StateContext.Provider value={store}>
|
||||
<DispatchContext.Provider value={{
|
||||
setCurrentPickedColor,
|
||||
setSelectedElement,
|
||||
setSelectedMenu,
|
||||
getCurrentColor,
|
||||
changeThemeColors,
|
||||
resetColors,
|
||||
saveColors,
|
||||
setSettingsByName,
|
||||
saveSettings,
|
||||
resetSettings,
|
||||
toggleShowPanel,
|
||||
setDefaultConfigs,
|
||||
handleLocalStorage,
|
||||
setCurrentCircleWidth,
|
||||
setCurrentSpeedoSize
|
||||
}}>
|
||||
{props.children}
|
||||
</DispatchContext.Provider>
|
||||
</StateContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useSettingsStorageState = () => useContext(StateContext)
|
||||
export const useSettingsStorageDispatch = () => useContext(DispatchContext)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default as HudStorageProvider } from "./HudStorage";
|
||||
export { default as SettingsStorageProvider } from "./SettingsStorage";
|
||||
36
resources/[esx_addons]/esx_hud/web/src/assets/Icons.jsx
Normal file
@@ -0,0 +1,36 @@
|
||||
export const HealthIcon = () => <svg className="absolute -translate-x-1/2 -translate-y-1/2 left-2/4 top-2/4" width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1_140)">
|
||||
<path d="M4.55509 10.9697C4.78954 11.1755 5.03155 11.3879 5.28049 11.6081C5.28219 11.6096 5.28392 11.6111 5.28565 11.6126L6.11382 12.3279C6.22477 12.4238 6.36248 12.4717 6.5002 12.4717C6.63791 12.4717 6.77566 12.4238 6.88662 12.3279L7.71462 11.6126C7.71636 11.6111 7.71805 11.6096 7.71975 11.6081C9.35917 10.1582 10.5883 9.04827 11.4776 7.96573C12.5163 6.70138 13 5.55819 13 4.36808C13 2.21489 11.3134 0.528259 9.1603 0.528259C8.19258 0.528259 7.23639 0.892654 6.5002 1.52432C5.7638 0.892615 4.80762 0.528259 3.83986 0.528259C1.68667 0.52822 0 2.21489 0 4.36804C0 6.97078 1.81212 8.56161 4.55509 10.9697ZM4.13585 5.31796H5.71191V3.74181H7.28805V5.31796H8.86415V6.89406H7.28805V8.47012H5.71191V6.89406H4.13585V5.31796Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1_140">
|
||||
<rect width="13" height="13" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
export const ArmorIcon = () => <svg className="absolute -translate-x-1/2 -translate-y-1/2 left-2/4 top-2/4" width="11" height="11" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1_117)">
|
||||
<path d="M3.01237 8.76801H0.574966V9.75083H3.01237V8.76801Z" fill="white"/>
|
||||
<path d="M3.01237 5.97266H0.574966V7.08832H3.01237V5.97266Z" fill="white"/>
|
||||
<path d="M10.4251 8.76801H7.98766V9.75083H10.4251V8.76801Z" fill="white"/>
|
||||
<path d="M9.78418 5.32815V4.95612C9.26531 4.88046 8.86551 4.43251 8.86551 3.89297V0H7.82362V1.23292C7.82362 2.51419 6.78122 3.55657 5.49998 3.55657C4.21874 3.55657 3.17634 2.51417 3.17634 1.23292V0H2.13443V3.89295C2.13443 4.43248 1.73465 4.88043 1.21576 4.9561V5.32812H3.65679V7.73287H1.21578V8.12354H3.65681V10.3954H1.21578V11H9.78418V10.3954H7.34315V8.12352H9.78418V7.73287H7.34315V5.32815H9.78418Z" fill="white"/>
|
||||
<path d="M10.4251 5.97266H7.98766V7.08832H10.4251V5.97266Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1_117">
|
||||
<rect width="11" height="11" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
export const DrinkIcon = () => <svg className="absolute -translate-x-1/2 -translate-y-1/2 left-2/4 top-2/4" width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.95689 1.08331L3.19526 11.9166H10.8103L12.0431 1.08331H1.95689ZM7 10.2916C6.06982 10.2916 5.31896 9.56581 5.31896 8.66665C5.31896 7.58331 7 5.74165 7 5.74165C7 5.74165 8.68103 7.58331 8.68103 8.66665C8.68103 9.56581 7.93017 10.2916 7 10.2916ZM10.547 4.33331H3.45301L3.20646 2.16665H10.7879L10.547 4.33331Z" fill="white"/>
|
||||
</svg>
|
||||
export const FoodIcon = () => <svg className="absolute -translate-x-1/2 -translate-y-1/2 left-2/4 top-2/4" width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.9167 7.04167C11.9167 7.64292 11.4346 8.125 10.8333 8.125H2.16666C1.87934 8.125 1.60379 8.01086 1.40063 7.8077C1.19746 7.60453 1.08333 7.32898 1.08333 7.04167C1.08333 6.75435 1.19746 6.4788 1.40063 6.27563C1.60379 6.07247 1.87934 5.95833 2.16666 5.95833H7.04166L8.39583 7.04167L9.75 5.95833H10.8333C11.1206 5.95833 11.3962 6.07247 11.5994 6.27563C11.8025 6.4788 11.9167 6.75435 11.9167 7.04167ZM6.5 1.625C1.62499 1.625 1.62499 4.875 1.62499 4.875H11.375C11.375 4.875 11.375 1.625 6.5 1.625ZM1.62499 9.75C1.62499 10.6492 2.35083 11.375 3.24999 11.375H9.75C10.6492 11.375 11.375 10.6492 11.375 9.75V9.20833H1.62499V9.75Z" fill="white"/>
|
||||
</svg>
|
||||
export const OxygenIcon = () => <svg className="absolute -translate-x-1/2 -translate-y-1/2 left-2/4 top-2/4" width="15" height="15" viewBox="0 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.9508 8.03355V8.74502C11.9508 9.02153 11.7265 9.24577 11.45 9.24577H8.54982C8.2733 9.24577 8.04906 9.02163 8.04906 8.74502V8.03355C8.04906 7.75703 8.2733 7.53279 8.54982 7.53279C8.86447 7.53279 9.11963 7.27764 9.11963 6.96299V0.872261C9.11963 0.606731 9.33482 0.391541 9.60035 0.391541H10.3994C10.6649 0.391541 10.8801 0.606731 10.8801 0.872261V6.96299C10.8801 7.27764 11.1353 7.53279 11.4499 7.53279C11.7265 7.53279 11.9508 7.75703 11.9508 8.03355ZM2.54828 7.12397C0.509974 9.80409 0.0886437 14.3408 0.00159123 16.1016C-0.0207821 16.5549 0.173154 16.9896 0.524516 17.277C0.843743 17.5382 1.25836 17.6529 1.66647 17.5929L5.56502 17.0202C5.87702 16.9743 6.16594 16.8292 6.38897 16.6062L6.78172 16.2134C7.05681 15.9383 7.21129 15.5653 7.21129 15.1763V5.41109C7.21129 3.7933 5.11775 3.7457 2.54828 7.12397ZM17.4514 7.12397C14.8821 3.7457 12.7884 3.7933 12.7884 5.41099V15.1762C12.7884 15.5652 12.943 15.9382 13.218 16.2133L13.6108 16.6061C13.8338 16.8291 14.1227 16.9742 14.4347 17.0201L18.3333 17.5928C18.7415 17.6528 19.156 17.5381 19.4752 17.2769C19.8265 16.9895 20.0205 16.5548 19.998 16.1015C19.9111 14.3408 19.4899 9.80409 17.4514 7.12397Z" fill="white"/>
|
||||
</svg>
|
||||
export const StaminaIcon = () => <svg width="15" height="15" xmlns="http://www.w3.org/2000/svg" className="absolute -translate-x-1/2 -translate-y-1/2 left-2/4 top-2/4" viewBox="0 0 416 512">
|
||||
<path d="M272 96c26.51 0 48-21.49 48-48S298.51 0 272 0s-48 21.49-48 48 21.49 48 48 48zM113.69 317.47l-14.8 34.52H32c-17.67 0-32 14.33-32 32s14.33 32 32 32h77.45c19.25 0 36.58-11.44 44.11-29.09l8.79-20.52-10.67-6.3c-17.32-10.23-30.06-25.37-37.99-42.61zM384 223.99h-44.03l-26.06-53.25c-12.5-25.55-35.45-44.23-61.78-50.94l-71.08-21.14c-28.3-6.8-57.77-.55-80.84 17.14l-39.67 30.41c-14.03 10.75-16.69 30.83-5.92 44.86s30.84 16.66 44.86 5.92l39.69-30.41c7.67-5.89 17.44-8 25.27-6.14l14.7 4.37-37.46 87.39c-12.62 29.48-1.31 64.01 26.3 80.31l84.98 50.17-27.47 87.73c-5.28 16.86 4.11 34.81 20.97 40.09 3.19 1 6.41 1.48 9.58 1.48 13.61 0 26.23-8.77 30.52-22.45l31.64-101.06c5.91-20.77-2.89-43.08-21.64-54.39l-61.24-36.14 31.31-78.28 20.27 41.43c8 16.34 24.92 26.89 43.11 26.89H384c17.67 0 32-14.33 32-32s-14.33-31.99-32-31.99z" fill="white"/>
|
||||
</svg>
|
||||
BIN
resources/[esx_addons]/esx_hud/web/src/assets/IndicatorSound.mp3
Normal file
469
resources/[esx_addons]/esx_hud/web/src/assets/translate.json
Normal file
@@ -0,0 +1,469 @@
|
||||
{
|
||||
"en": {
|
||||
"General": {
|
||||
"status": "Status",
|
||||
"speedo": "Speedometer",
|
||||
"settings": "Settings",
|
||||
"reset": "Reset",
|
||||
"save": "Save",
|
||||
"info": "Click any colorpicker icon if you want change colors!",
|
||||
"currentedit": "Current edit:"
|
||||
},
|
||||
"Status": {
|
||||
"healthbar": "Health bar",
|
||||
"armorbar": "Armor bar",
|
||||
"drinkbar": "Drink bar",
|
||||
"foodbar": "Food bar",
|
||||
"oxygenbar": "Oxygen bar",
|
||||
"staminabar": "Stamina bar",
|
||||
"circlewidth": "Status circle width"
|
||||
},
|
||||
"Speedo": {
|
||||
"segment-color": "segment color",
|
||||
"segment-progress-color": "segment progress color",
|
||||
"number-color": "number color",
|
||||
"danger-color": "danger color",
|
||||
"danger-progress-color": "danger progress color",
|
||||
"number-danger-color": "number danger color",
|
||||
"speedo-progress-color": "speedo progress color",
|
||||
"damage-progress-color": "damage progress color",
|
||||
"engine-icon-color": "engine icon color",
|
||||
"tempomat-icon-color": "tempomat icon color",
|
||||
"light-icon-color": "light icon color",
|
||||
"door-icon-color": "door icon color",
|
||||
"fuel-icon-color": "fuel icon color",
|
||||
"fuel-level-color": "fuel level color",
|
||||
"mileage-level-color": "mileage level color",
|
||||
"unit-color": "unit color",
|
||||
"current-speed-color": "current speed color",
|
||||
"left-right-index-color": "left right index color",
|
||||
"damage-icon-color": "damage icon color",
|
||||
"speedo-background-color": "speedo background color",
|
||||
"speedo-outer-circle-color": "speedo outer circle color",
|
||||
"speedo-nooble-color": "speedo nooble color",
|
||||
"speedo-nooble-container": "speedo nooble container",
|
||||
"resize-speedo": "resize speedo",
|
||||
"speedo-seatbelt-icon-color": "speedo seatbelt icon color"
|
||||
},
|
||||
"Settings": {
|
||||
"status": "Status HUD ON/OFF",
|
||||
"vehicle": "Vehicle HUD ON/OFF",
|
||||
"weapon": "Weapon HUD ON/OFF",
|
||||
"position": "Position HUD ON/OFF",
|
||||
"voice": "Voice HUD ON/OFF",
|
||||
"money": "Money HUD ON/OFF",
|
||||
"info": "Info HUD ON/OFF",
|
||||
"indicatorsound": "Indicator sound ON/OFF",
|
||||
"indicatorseatbeltsound":"Seatbelt sound ON/OFF",
|
||||
"minimaponfoot": "Minimap on foot ON/OFF",
|
||||
"vehiclehandlers":"Vehicle handlers(Engine toggle, Indicator lights) ON/OFF",
|
||||
"needle": "Needle ON/OFF",
|
||||
"kmh": "KMH",
|
||||
"mph": "MPH",
|
||||
"changeunit":"Change unit:",
|
||||
"statuspercent": "Status percent ON/OFF",
|
||||
"centerstatuses": "Center statuses ON/OFF",
|
||||
"passengerspeedo":"Passenger speedo ON/OFF"
|
||||
}
|
||||
},
|
||||
"de": {
|
||||
"General": {
|
||||
"status": "Status",
|
||||
"speedo": "Geschwindigkeitszähler",
|
||||
"settings": "Einstellungen",
|
||||
"reset": "Zurücksetzen",
|
||||
"save": "Speichern",
|
||||
"info": "Jede Farbe auswählen um die Farbe zu ändern",
|
||||
"currentedit": "Derzeitige Bearbeitung:"
|
||||
},
|
||||
"Status": {
|
||||
"healthbar": "Heilungsleiste",
|
||||
"armorbar": "Weste",
|
||||
"drinkbar": "Trinken",
|
||||
"foodbar": "Essen",
|
||||
"oxygenbar": "Luft",
|
||||
"staminabar": "Ausdauer",
|
||||
"circlewidth": "Status Kreisbreite"
|
||||
},
|
||||
"Speedo": {
|
||||
"segment-color": "Segmentfarbe",
|
||||
"segment-progress-color": "Segmentfortschrittsfarbe",
|
||||
"number-color": "Nummerfarbe",
|
||||
"danger-color": "Gefahrenfarbe",
|
||||
"danger-progress-color": "Gefahrenfortschrittsfarbe",
|
||||
"number-danger-color": "Nummernfortschrittsfarbe",
|
||||
"speedo-progress-color": "Geschwindigkeitsfortschrittsfarbe",
|
||||
"damage-progress-color": "Schadensfortschrittsfarbe",
|
||||
"engine-icon-color": "Motor Bild Farbe",
|
||||
"tempomat-icon-color": "Tempomat Bild Farbe",
|
||||
"light-icon-color": "Licht Bild FaRBE",
|
||||
"door-icon-color": "Tür Bild Farbe",
|
||||
"fuel-icon-color": "Benzin Bild Farbe",
|
||||
"fuel-level-color": "Benzinanzeige Farbe",
|
||||
"mileage-level-color": "Kilometerstand Farbe",
|
||||
"unit-color": "Einheitenfarbe",
|
||||
"current-speed-color": "Derzeitige Geschwindkeitsfarbe",
|
||||
"left-right-index-color": "Links Rechts Index Farbe",
|
||||
"damage-icon-color": "Schaden Bild Farbe",
|
||||
"speedo-background-color": "Geschwindigkeit Hintergrundsfarbe",
|
||||
"speedo-outer-circle-color": "Tacho Farbe",
|
||||
"speedo-nooble-color": "Tacho Nooble Farbe",
|
||||
"speedo-nooble-container": "Tacho Noble container",
|
||||
"resize-speedo": "resize speedo",
|
||||
"speedo-seatbelt-icon-color": "speedo seatbelt icon color"
|
||||
},
|
||||
"Settings": {
|
||||
"status": "Status HUD AN/AUS",
|
||||
"vehicle": "Fahrzeug HUD AN/AUS",
|
||||
"weapon": "Waffen HUD AN/AUS",
|
||||
"position": "Positions HUD AN/AUS",
|
||||
"voice": "Stimmen HUD AN/AUS",
|
||||
"money": "Geld HUD AN/AUS",
|
||||
"info": "Info HUD AN/AUS",
|
||||
"indicatorsound": "Blinker Ton AN/AUS",
|
||||
"indicatorseatbeltsound":"Seatbelt sound ON/OFF",
|
||||
"minimaponfoot": "Minimap zu Fuß AN/AUS",
|
||||
"vehiclehandlers":"Fahrzeug Infos(Motor An/Ausschalten, Blinker) AN/AUS",
|
||||
"needle": "Nadel AN/AUS",
|
||||
"kmh": "KMH",
|
||||
"mph": "MPH",
|
||||
"changeunit":"Unit Ändern:",
|
||||
"statuspercent": "Status prozent AN/AUS",
|
||||
"centerstatuses": "Mittel Statusse AN/AUS",
|
||||
"passengerspeedo":"Beifahrer Tacho AN/AUS"
|
||||
}
|
||||
},
|
||||
"hu": {
|
||||
"General": {
|
||||
"status": "Státusz",
|
||||
"speedo": "Sebességmérő",
|
||||
"settings": "Beállítások",
|
||||
"reset": "Alapértelmezett",
|
||||
"save": "Mentés",
|
||||
"info": "Nyomj a színtáblára a színek változtatásához!",
|
||||
"currentedit": "Jelenlegi módosítás:"
|
||||
},
|
||||
"Status": {
|
||||
"healthbar": "Élet státusz",
|
||||
"armorbar": "Pajzs státusz",
|
||||
"drinkbar": "Ital státusz",
|
||||
"foodbar": "Étel státusz",
|
||||
"oxygenbar": "Oxigén státusz",
|
||||
"staminabar": "Stamina státusz",
|
||||
"circlewidth": "Státusz kör vastagsága"
|
||||
},
|
||||
"Speedo": {
|
||||
"segment-color": "Sebességmérő színe",
|
||||
"segment-progress-color": "Aktuális sebesség színe",
|
||||
"number-color": "Sebességmérő szám színe",
|
||||
"danger-color": "Figyelmeztetés színe",
|
||||
"danger-progress-color": "Figyelmeztetés státusz színe",
|
||||
"number-danger-color": "Sebességmérő veszélyes tartomány színe",
|
||||
"speedo-progress-color": "Fordulatszám mérő színe",
|
||||
"damage-progress-color": "Sérülés mérő színe",
|
||||
"engine-icon-color": "Motor ikon szín",
|
||||
"tempomat-icon-color": "Tempomat ikon szín",
|
||||
"light-icon-color": "Fényszóró ikon szín",
|
||||
"door-icon-color": "Ajtó ikon szín",
|
||||
"fuel-icon-color": "Üzemanyag ikon szín",
|
||||
"fuel-level-color": "Üzemanyag szint szín",
|
||||
"mileage-level-color": "Óra állás színe",
|
||||
"unit-color": "Mértékegység szín",
|
||||
"current-speed-color": "Jelenlegi sebesség szín",
|
||||
"left-right-index-color": "Index szín",
|
||||
"damage-icon-color": "Sérülés ikon szín",
|
||||
"speedo-background-color": "Mérőlap háttér színe",
|
||||
"speedo-outer-circle-color": "Mérőegység keret színe",
|
||||
"speedo-nooble-color": "Sebességmérő tű szín",
|
||||
"speedo-nooble-container": "Sebességmérő tű körlap színe",
|
||||
"resize-speedo": "Sebességmérő átméretezése",
|
||||
"speedo-seatbelt-icon-color": "Biztonsági öv ikon színe"
|
||||
},
|
||||
"Settings": {
|
||||
"status": "Státusz HUD BE/KI",
|
||||
"vehicle": "Jármű HUD BE/KI",
|
||||
"weapon": "Fegyver HUD BE/KI",
|
||||
"position": "Pozíció HUD BE/KI",
|
||||
"voice": "Hang HUD BE/KI",
|
||||
"money": "Pénz HUD BE/KI",
|
||||
"info": "Infó HUD BE/KI",
|
||||
"indicatorsound": "Indikátor hang BE/KI",
|
||||
"indicatorseatbeltsound":"Biztonsági öv hang BE/KI",
|
||||
"minimaponfoot": "Minimap járműn kívül BE/KI",
|
||||
"vehiclehandlers": "Jármű opciók(Motor indítás, Indexek) BE/KI",
|
||||
"needle": "Sebességmérő tű BE/KI",
|
||||
"kmh": "KMH",
|
||||
"mph": "MPH",
|
||||
"changeunit": "Sebesség mértékegysége:",
|
||||
"statuspercent": "Státusz százalék BE/KI",
|
||||
"centerstatuses": "Státusz középre mozgatás BE/KI",
|
||||
"passengerspeedo":"Kilóméter óra anyós ülésen BE/KI"
|
||||
}
|
||||
},
|
||||
"sr": {
|
||||
"General": {
|
||||
"status": "Status",
|
||||
"speedo": "Brzinometar",
|
||||
"settings": "Podesavanja",
|
||||
"reset": "Reset",
|
||||
"save": "Sacuvaj",
|
||||
"info": "Klikni na ikonicu ako zelis da promenis boju!",
|
||||
"currentedit": "Trenutno editovanje:"
|
||||
},
|
||||
"Status": {
|
||||
"healthbar": "Traka zdravlja",
|
||||
"armorbar": "Traka pancira",
|
||||
"drinkbar": "Traka pica",
|
||||
"foodbar": "Traka hrane",
|
||||
"oxygenbar": "Traka vazduha",
|
||||
"staminabar": "Traka izdrzljivosti",
|
||||
"circlewidth": "Sirina statusnog kruga"
|
||||
},
|
||||
"Speedo": {
|
||||
"segment-color": "boja segmenta",
|
||||
"segment-progress-color": "boja progresa segmenta",
|
||||
"number-color": "boja broja",
|
||||
"danger-color": "boja upozorenja",
|
||||
"danger-progress-color": "boja progresa upozorenja",
|
||||
"number-danger-color": "boja broja upozorenja",
|
||||
"speedo-progress-color": "boja progresa brzinometra",
|
||||
"damage-progress-color": "boja progresa ostecenosti",
|
||||
"engine-icon-color": "boja ikonice motora",
|
||||
"tempomat-icon-color": "boja ikonice tempomata",
|
||||
"light-icon-color": "boja ikonice svetala",
|
||||
"door-icon-color": "boja ikonice vrata",
|
||||
"fuel-icon-color": "boja ikonice goriva",
|
||||
"fuel-level-color": "boja nivoa goriva",
|
||||
"mileage-level-color": "boja kilometraze",
|
||||
"unit-color": "unit boja",
|
||||
"current-speed-color": "boja trenutne brzine",
|
||||
"left-right-index-color": "boja migavaca",
|
||||
"damage-icon-color": "boja ikonice ostecenja",
|
||||
"speedo-background-color": "pozadinska boja brzinometra",
|
||||
"speedo-outer-circle-color": "boja kruga brzinometra",
|
||||
"speedo-nooble-color": "nooble boja brzinometra",
|
||||
"speedo-nooble-container": "brzinometar nooble container",
|
||||
"resize-speedo": "Speedo resize",
|
||||
"speedo-seatbelt-icon-color": "speedo seatbelt icon color"
|
||||
},
|
||||
"Settings": {
|
||||
"status": "Status HUD ON/OFF",
|
||||
"vehicle": "HUD Vozila ON/OFF",
|
||||
"weapon": "HUD Oruzja ON/OFF",
|
||||
"position": "Pozicija HUD ON/OFF",
|
||||
"voice": "Glasovni HUD ON/OFF",
|
||||
"money": "Novac HUD ON/OFF",
|
||||
"info": "Info HUD ON/OFF",
|
||||
"indicatorsound": "Zvukovi Indikatora ON/OFF",
|
||||
"indicatorseatbeltsound":"Seatbelt sound ON/OFF",
|
||||
"minimaponfoot": "Minimapa van vozila ON/OFF",
|
||||
"vehiclehandlers":"Delovi Vozila (Motor, Svetla) ON/OFF",
|
||||
"needle": "Igla ON/OFF",
|
||||
"kmh": "KMH",
|
||||
"mph": "MPH",
|
||||
"changeunit":"Promeni jedinicu:",
|
||||
"statuspercent": "Procenti Statusa ON/OFF",
|
||||
"centerstatuses": "Centrirani Statusi ON/OFF",
|
||||
"passengerspeedo":"Brzinometar Putnika ON/OFF"
|
||||
}
|
||||
},
|
||||
"nl": {
|
||||
"General": {
|
||||
"status": "Status",
|
||||
"speedo": "Snelheidsmeter",
|
||||
"settings": "Instellingen",
|
||||
"reset": "Reset",
|
||||
"save": "Opslaan",
|
||||
"info": "Klik op een kleurkiezer als u de kleuren wilt veranderen.!",
|
||||
"currentedit": "Huidige bewerking:"
|
||||
},
|
||||
"Status": {
|
||||
"healthbar": "Gezondheidsbar",
|
||||
"armorbar": "Pantserbar",
|
||||
"drinkbar": "Dorst bar",
|
||||
"foodbar": "Honger bar",
|
||||
"oxygenbar": "Zuurstof bar",
|
||||
"staminabar": "Stamina bar",
|
||||
"circlewidth": "Breedte status cirkel"
|
||||
},
|
||||
"Speedo": {
|
||||
"segment-color": "kleursegment",
|
||||
"segment-progress-color": "segment voortgang kleur",
|
||||
"number-color": "nummerkleur",
|
||||
"danger-color": "gevarenkleur",
|
||||
"danger-progress-color": "gevaar voortgang kleur",
|
||||
"number-danger-color": "kleur gevarennummer",
|
||||
"speedo-progress-color": "kleur snelheidsmeter voortgang",
|
||||
"damage-progress-color": "kleur schade voortgang",
|
||||
"engine-icon-color": "kleur motor icoon",
|
||||
"tempomat-icon-color": "kleur tempomat icoon",
|
||||
"light-icon-color": "kleur lichtpictogram",
|
||||
"door-icon-color": "kleur deur icoon",
|
||||
"fuel-icon-color": "kleur brandstof icoon",
|
||||
"fuel-level-color": "kleur brandstof level",
|
||||
"mileage-level-color": "kilometerstand kleur",
|
||||
"unit-color": "eenheid kleur",
|
||||
"current-speed-color": "huidige snelheid kleur",
|
||||
"left-right-index-color": "links rechts index kleur",
|
||||
"damage-icon-color": "kleur schadepictogram",
|
||||
"speedo-background-color": "snelheidsmeter achtergrond kleur",
|
||||
"speedo-outer-circle-color": "kleur snelheidsmeter buitenste cirkel",
|
||||
"speedo-nooble-color": "kleur snelheidsmeter nooble",
|
||||
"speedo-nooble-container": "snelheidsmeter nooble container",
|
||||
"speedo-seatbelt-icon-color": "speedo seatbelt icon color"
|
||||
},
|
||||
"Settings": {
|
||||
"status": "Status HUD AAN/UIT",
|
||||
"vehicle": "Voertuig HUD AAN/UIT",
|
||||
"weapon": "Wapen HUD AAN/UIT",
|
||||
"position": "Positie HUD AAN/UIT",
|
||||
"voice": "Spraak HUD AAN/UIT",
|
||||
"money": "Geld HUD AAN/UIT",
|
||||
"info": "Info HUD AAN/UIT",
|
||||
"indicatorsound": "Indicator geluid AAN/UIT",
|
||||
"indicatorseatbeltsound":"Seatbelt sound ON/OFF",
|
||||
"minimaponfoot": "Minimap te voet AAN/UIT",
|
||||
"vehiclehandlers":"Voertuig handlers(Motor toggle, Indicator lichten) AAN/UIT",
|
||||
"needle": "Naald AAN/UIT",
|
||||
"kmh": "KMH",
|
||||
"mph": "MPH",
|
||||
"changeunit":"Verander eenheid:",
|
||||
"statuspercent": "Status procent AAN/UIT",
|
||||
"centerstatuses": "Centreer statussen AAN/UIT",
|
||||
"passengerspeedo":"Passagier snelheidsmeter AAN/UIT"
|
||||
}
|
||||
},
|
||||
"it": {
|
||||
"General": {
|
||||
"status": "Stato",
|
||||
"speedo": "Contakilometri",
|
||||
"settings": "Impostazioni",
|
||||
"reset": "Resetta",
|
||||
"save": "Salva",
|
||||
"info": "Clicca un campione di colore per cambiarlo!",
|
||||
"currentedit": "Modifica attuale:"
|
||||
},
|
||||
"Status": {
|
||||
"healthbar": "Bassa Salute",
|
||||
"armorbar": "Barra Armatura",
|
||||
"drinkbar": "Barra Sete",
|
||||
"foodbar": "Barra Fame",
|
||||
"oxygenbar": "Barra ossigeno",
|
||||
"staminabar": "Barra Stamina",
|
||||
"circlewidth": "Larghezza cerchio status"
|
||||
},
|
||||
"Speedo": {
|
||||
"segment-color": "Colore segmento",
|
||||
"segment-progress-color": "Colore segmento in uso",
|
||||
"number-color": "Colore numero",
|
||||
"danger-color": "Colore emergenza",
|
||||
"danger-progress-color": "Colore emergenza in uso",
|
||||
"number-danger-color": "Colore numero pericolo",
|
||||
"speedo-progress-color": "Colore segmento contakm",
|
||||
"damage-progress-color": "Colore segmento danno",
|
||||
"engine-icon-color": "Colore icone motore",
|
||||
"tempomat-icon-color": "Colore icona tempomat",
|
||||
"light-icon-color": "Colore icona chiaro",
|
||||
"door-icon-color": "Colore icona porte",
|
||||
"fuel-icon-color": "Colore icona carburante",
|
||||
"fuel-level-color": "Colore livello carburante",
|
||||
"mileage-level-color": "Colore kilometraggio",
|
||||
"unit-color": "Colore unità",
|
||||
"current-speed-color": "Colore velocità attuale",
|
||||
"left-right-index-color": "Colore freccia destra sinistra",
|
||||
"damage-icon-color": "Colore icona danno",
|
||||
"speedo-background-color": "Colore sfondo contakm",
|
||||
"speedo-outer-circle-color": "Colore cerchio esterno contakm",
|
||||
"speedo-nooble-color": "Colore nooble contakm",
|
||||
"speedo-nooble-container": "Container nooble contakm",
|
||||
"resize-speedo": "Dimensione contakm",
|
||||
"speedo-seatbelt-icon-color": "Colore icona cintura"
|
||||
},
|
||||
"Settings": {
|
||||
"status": "Stato HUD ON/OFF",
|
||||
"vehicle": "Veicolo HUD ON/OFF",
|
||||
"weapon": "Armi HUD ON/OFF",
|
||||
"position": "Posizione HUD ON/OFF",
|
||||
"voice": "Voce HUD ON/OFF",
|
||||
"money": "Denaro HUD ON/OFF",
|
||||
"info": "Info HUD ON/OFF",
|
||||
"indicatorsound": "Suono indicatori ON/OFF",
|
||||
"indicatorseatbeltsound":"Suono cintura ON/OFF",
|
||||
"minimaponfoot": "Minimappa a piedi ON/OFF",
|
||||
"vehiclehandlers":"Accessori veicolo(stato motore, frecce di indicazione) ON/OFF",
|
||||
"needle": "Ago ON/OFF",
|
||||
"kmh": "KMH",
|
||||
"mph": "MPH",
|
||||
"changeunit":"Cambia unità:",
|
||||
"statuspercent": "Percentuale Status ON/OFF",
|
||||
"centerstatuses": "Accentra Status ON/OFF",
|
||||
"passengerspeedo":"Contakm per passeggero ON/OFF"
|
||||
}
|
||||
},
|
||||
"fr": {
|
||||
"General": {
|
||||
"status": "Status",
|
||||
"speedo": "Compteur de vitesse",
|
||||
"settings": "Paramètres",
|
||||
"reset": "Réinitialiser",
|
||||
"save": "Sauvegarder",
|
||||
"info": "Cliquez sur n'importe quelle icône pour le modifier!",
|
||||
"currentedit": "Edition en cours:"
|
||||
},
|
||||
"Status": {
|
||||
"healthbar": "Barre de vie",
|
||||
"armorbar": "Barre d'armure",
|
||||
"drinkbar": "Barre de soif",
|
||||
"foodbar": "Barre de faim",
|
||||
"oxygenbar": "Barre d'oxygène",
|
||||
"staminabar": "Barre d'endurance",
|
||||
"circlewidth": "Largeur du cercle"
|
||||
},
|
||||
"Speedo": {
|
||||
"segment-color": "Couleur segment",
|
||||
"segment-progress-color": "Couleurs progression segment",
|
||||
"number-color": "Couleur des numéro",
|
||||
"danger-color": "Couleur sur-regime",
|
||||
"danger-progress-color": "Couleur barre sur-régime",
|
||||
"number-danger-color": "Couleur numéro sur-regime",
|
||||
"speedo-progress-color": "Couleur barre vitessee",
|
||||
"damage-progress-color": "Couleur barre dégâts",
|
||||
"engine-icon-color": "Couleur icône moteur",
|
||||
"tempomat-icon-color": "Couleur icône Cruise control",
|
||||
"light-icon-color": "Couleur icône phare",
|
||||
"door-icon-color": "Couleur icône porte",
|
||||
"fuel-icon-color": "Couleur icône carburant",
|
||||
"fuel-level-color": "Couleur niveau carburant",
|
||||
"mileage-level-color": "Couleur kilométrage",
|
||||
"unit-color": "Couleur unité vitesse",
|
||||
"current-speed-color": "Couleur vitesse actuel",
|
||||
"left-right-index-color": "Couleur des clignotant",
|
||||
"damage-icon-color": "Couleru icône dégâts",
|
||||
"speedo-background-color": "Couleur arrière plan",
|
||||
"speedo-outer-circle-color": "couleur du cercle extérieur",
|
||||
"speedo-nooble-color": "couleur de l'aguiller",
|
||||
"speedo-nooble-container": "couleur fixation aiguille",
|
||||
"speedo-seatbelt-icon-color": "speedo seatbelt icon color"
|
||||
},
|
||||
"Settings": {
|
||||
"status": "HUD Status ON/OFF",
|
||||
"vehicle": "HUD Véhicule ON/OFF",
|
||||
"weapon": "HUD Armes ON/OFF",
|
||||
"position": "HUD Position ON/OFF",
|
||||
"voice": "HUD Voix ON/OFF",
|
||||
"money": "HUD Argent ON/OFF",
|
||||
"info": "Info HUD ON/OFF",
|
||||
"indicatorsound": "Sons Clignotant ON/OFF",
|
||||
"indicatorseatbeltsound":"Seatbelt sound ON/OFF",
|
||||
"minimaponfoot": "Minimap à piedt ON/OFF",
|
||||
"vehiclehandlers":"Véhicule (Moteur, clignotants) ON/OFF",
|
||||
"needle": "Aiguille compteur ON/OFF",
|
||||
"kmh": "KMH",
|
||||
"mph": "MPH",
|
||||
"changeunit":"Changer d'unité :",
|
||||
"statuspercent": "Status en pourçent ON/OFF",
|
||||
"centerstatuses": "Status centrer ON/OFF",
|
||||
"passengerspeedo":"Compteur en passager ON/OFF"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 17 KiB |
BIN
resources/[esx_addons]/esx_hud/web/src/assets/weapons/ball.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 10 KiB |
BIN
resources/[esx_addons]/esx_hud/web/src/assets/weapons/bzgas.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
BIN
resources/[esx_addons]/esx_hud/web/src/assets/weapons/hammer.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 3.1 KiB |