mirror of
https://github.com/Michatec/xhud.git
synced 2026-03-31 23:46:29 +02:00
First
This commit is contained in:
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.lua]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = tab
|
||||||
70
README.md
Normal file
70
README.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# xhud
|
||||||
|
|
||||||
|
xhud is a FiveM HUD for ox_core or ESX Legacy.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- ox_lib
|
||||||
|
|
||||||
|
This also requires a framework of your choice between ox_core and es_extended.
|
||||||
|
Note that if you are using ESX, you will also need esx_status and esx_basicneeds.
|
||||||
|
|
||||||
|
## Download & Installation
|
||||||
|
|
||||||
|
- Go to the [releases page](https://github.com/Michatec/xhud/releases "Releases page") and download the latest release
|
||||||
|
- Place it inside the `resources` directory
|
||||||
|
- Add the resource to your `server.cfg` after dependencies to make sure it's started correctly at server startup:
|
||||||
|
|
||||||
|
``` command
|
||||||
|
ensure xhud
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
You can add these settings directly to your 'server.cfg', or add them to a separate file (i.e. hud.cfg) and call it with exec. **Convars must be set before starting xhud.**
|
||||||
|
|
||||||
|
The values below are defaults and should not be explicitly set unless changing the value.
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
### Shared
|
||||||
|
|
||||||
|
# Seabelt system
|
||||||
|
setr hud:seatbelt false
|
||||||
|
|
||||||
|
### Client
|
||||||
|
|
||||||
|
# Stress Indicator
|
||||||
|
setr hud:stress false
|
||||||
|
|
||||||
|
# Stamina Indicator
|
||||||
|
setr hud:stamina false
|
||||||
|
|
||||||
|
# Fuel Indicator
|
||||||
|
setr hud:fuel false
|
||||||
|
|
||||||
|
# Vehicles speed: "imperial" or "metric"
|
||||||
|
setr hud:unitsystem "imperial"
|
||||||
|
|
||||||
|
# Radar mode: by default, the radar is only enabled while sitting on a vehicle.
|
||||||
|
# Set this to true to have it always enabled. This will also enable the map cycler.
|
||||||
|
setr hud:persistentRadar false
|
||||||
|
|
||||||
|
# Radar shape
|
||||||
|
setr hud:circleMap true
|
||||||
|
|
||||||
|
# Keys for map cycler and seatbelt
|
||||||
|
setr hud:cyclemapKey "Z"
|
||||||
|
setr hud:seatbeltKey "B"
|
||||||
|
|
||||||
|
# Voice Indicator
|
||||||
|
setr hud:voice false
|
||||||
|
|
||||||
|
# Voice system: "pma-voice" or "saltychat"
|
||||||
|
setr hud:voiceService "pma-voice"
|
||||||
|
|
||||||
|
# Server logo
|
||||||
|
setr hud:logo true
|
||||||
|
|
||||||
|
# Version check against GitHub repo (Recommended)
|
||||||
|
setr hud:versioncheck true
|
||||||
|
```
|
||||||
60
client/frameworks.lua
Normal file
60
client/frameworks.lua
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
if GetResourceState('ox_core'):find('start') then
|
||||||
|
local file = ('imports/%s.lua'):format(IsDuplicityVersion() and 'server' or 'client')
|
||||||
|
local import = LoadResourceFile('ox_core', file)
|
||||||
|
local chunk = assert(load(import, ('@@ox_core/%s'):format(file)))
|
||||||
|
chunk()
|
||||||
|
|
||||||
|
if player then
|
||||||
|
PlayerLoaded = true
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent('ox:playerLoaded', function()
|
||||||
|
PlayerLoaded = true
|
||||||
|
InitializeHUD()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('ox:playerLogout', function()
|
||||||
|
PlayerLoaded = false
|
||||||
|
HUD = false
|
||||||
|
SendMessage('toggleHud', HUD)
|
||||||
|
end)
|
||||||
|
|
||||||
|
AddEventHandler('ox:statusTick', function(values)
|
||||||
|
SendMessage('status', values)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if GetResourceState('es_extended'):find('start') then
|
||||||
|
local ESX = exports['es_extended']:getSharedObject()
|
||||||
|
if ESX.PlayerLoaded then
|
||||||
|
PlayerLoaded = true
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:playerLoaded')
|
||||||
|
AddEventHandler('esx:playerLoaded', function()
|
||||||
|
PlayerLoaded = true
|
||||||
|
InitializeHUD()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:onPlayerLogout')
|
||||||
|
AddEventHandler('esx:onPlayerLogout', function()
|
||||||
|
PlayerLoaded = false
|
||||||
|
HUD = false
|
||||||
|
SendMessage('toggleHud', HUD)
|
||||||
|
end)
|
||||||
|
|
||||||
|
AddEventHandler('esx_status:onTick', function(data)
|
||||||
|
local hunger, thirst, stress
|
||||||
|
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
|
||||||
|
if data[i].name == 'stress' then stress = math.floor(data[i].percent) end
|
||||||
|
end
|
||||||
|
|
||||||
|
SendMessage('status', {
|
||||||
|
hunger = hunger,
|
||||||
|
thirst = thirst,
|
||||||
|
stress = GetConvar('hud:stress', 'false') and stress,
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
end
|
||||||
58
client/hud.lua
Normal file
58
client/hud.lua
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
local curPaused
|
||||||
|
local lastHealth, lastArmour
|
||||||
|
local onSurface, isResting
|
||||||
|
|
||||||
|
CreateThread(function()
|
||||||
|
while true do
|
||||||
|
if HUD then
|
||||||
|
local paused = IsPauseMenuActive()
|
||||||
|
if paused ~= curPaused then
|
||||||
|
SendMessage('toggleHud', not paused)
|
||||||
|
curPaused = paused
|
||||||
|
end
|
||||||
|
|
||||||
|
local curHealth = GetEntityHealth(cache.ped)
|
||||||
|
if curHealth ~= lastHealth then
|
||||||
|
SendMessage('setHealth', {
|
||||||
|
current = curHealth,
|
||||||
|
max = GetEntityMaxHealth(cache.ped)
|
||||||
|
})
|
||||||
|
lastHealth = curHealth
|
||||||
|
end
|
||||||
|
|
||||||
|
local curArmour = GetPedArmour(cache.ped)
|
||||||
|
if curArmour ~= lastArmour then
|
||||||
|
SendMessage('setArmour', curArmour)
|
||||||
|
lastArmour = curArmour
|
||||||
|
end
|
||||||
|
|
||||||
|
if GetConvar('hud:stamina', 'false') == 'true' then
|
||||||
|
local curStamina = GetPlayerStamina(cache.playerId)
|
||||||
|
local maxStamina = GetPlayerMaxStamina(cache.playerId)
|
||||||
|
if curStamina < maxStamina then
|
||||||
|
SendMessage('setStamina', {
|
||||||
|
current = curStamina,
|
||||||
|
max = maxStamina
|
||||||
|
})
|
||||||
|
isResting = false
|
||||||
|
elseif not isResting then
|
||||||
|
SendMessage('setStamina', false)
|
||||||
|
isResting = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local curUnderwaterTime = GetPlayerUnderwaterTimeRemaining(cache.playerId)
|
||||||
|
if curUnderwaterTime < maxUnderwaterTime then
|
||||||
|
SendMessage('setOxygen', {
|
||||||
|
current = curUnderwaterTime,
|
||||||
|
max = maxUnderwaterTime
|
||||||
|
})
|
||||||
|
onSurface = false
|
||||||
|
elseif not onSurface then
|
||||||
|
SendMessage('setOxygen', false)
|
||||||
|
onSurface = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Wait(200)
|
||||||
|
end
|
||||||
|
end)
|
||||||
68
client/minimap.lua
Normal file
68
client/minimap.lua
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
local mapLimit
|
||||||
|
local mapState = 1
|
||||||
|
local persistentRadar = GetConvar('hud:persistentRadar', 'false')
|
||||||
|
|
||||||
|
if GetConvar('hud:circleMap', 'true') == 'true' then
|
||||||
|
mapLimit = 1
|
||||||
|
else
|
||||||
|
mapLimit = 3
|
||||||
|
end
|
||||||
|
|
||||||
|
if persistentRadar == 'true' then
|
||||||
|
local function setRadarState()
|
||||||
|
if mapState == 0 then
|
||||||
|
DisplayRadar(false)
|
||||||
|
elseif mapState == 1 then
|
||||||
|
DisplayRadar(true)
|
||||||
|
SetBigmapActive(false, false)
|
||||||
|
elseif mapState == 2 then
|
||||||
|
DisplayRadar(true)
|
||||||
|
SetBigmapActive(true, false)
|
||||||
|
elseif mapState == 3 then
|
||||||
|
DisplayRadar(true)
|
||||||
|
SetBigmapActive(true, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
CreateThread(function()
|
||||||
|
repeat Wait(100) until HUD
|
||||||
|
setRadarState()
|
||||||
|
end)
|
||||||
|
|
||||||
|
lib.addKeybind({
|
||||||
|
name = 'cyclemap',
|
||||||
|
description = 'Cycle Map',
|
||||||
|
defaultKey = GetConvar('hud:cyclemapKey', 'Z'),
|
||||||
|
onPressed = function()
|
||||||
|
if mapState == mapLimit then
|
||||||
|
mapState = 0
|
||||||
|
else
|
||||||
|
mapState += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
setRadarState()
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
CreateThread(function()
|
||||||
|
local minimap = RequestScaleformMovie('minimap')
|
||||||
|
repeat Wait(100) until HasScaleformMovieLoaded(minimap)
|
||||||
|
while true do
|
||||||
|
if HUD then
|
||||||
|
BeginScaleformMovieMethod(minimap, 'SETUP_HEALTH_ARMOUR')
|
||||||
|
ScaleformMovieMethodAddParamInt(3)
|
||||||
|
EndScaleformMovieMethod()
|
||||||
|
|
||||||
|
if persistentRadar == 'false' then
|
||||||
|
local isRadarHidden = IsRadarHidden()
|
||||||
|
local isPedUsingAnyVehicle = cache.vehicle and true or false
|
||||||
|
if isPedUsingAnyVehicle == isRadarHidden then
|
||||||
|
DisplayRadar(isPedUsingAnyVehicle)
|
||||||
|
SetRadarZoom(1150)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Wait(500)
|
||||||
|
end
|
||||||
|
end)
|
||||||
62
client/seatbelt.lua
Normal file
62
client/seatbelt.lua
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
if GetConvar('hud:seatbelt', 'false') == 'true' then
|
||||||
|
local isBuckled = false
|
||||||
|
SetFlyThroughWindscreenParams(15.0, 20.0, 17.0, 2000.0)
|
||||||
|
|
||||||
|
local function Buckled()
|
||||||
|
CreateThread(function()
|
||||||
|
while isBuckled do
|
||||||
|
lib.disableControls()
|
||||||
|
Wait(0)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Seatbelt(status)
|
||||||
|
if status then
|
||||||
|
SendMessage('playSound', 'buckle')
|
||||||
|
SendMessage('setSeatbelt', { toggled = true, buckled = true })
|
||||||
|
SetFlyThroughWindscreenParams(1000.0, 1000.0, 0.0, 0.0)
|
||||||
|
lib.disableControls:Add(75)
|
||||||
|
Buckled()
|
||||||
|
else
|
||||||
|
SendMessage('playSound', 'unbuckle')
|
||||||
|
SendMessage('setSeatbelt', { toggled = true, buckled = false })
|
||||||
|
SetFlyThroughWindscreenParams(15.0, 20.0, 17.0, 2000.0)
|
||||||
|
lib.disableControls:Remove(75)
|
||||||
|
end
|
||||||
|
isBuckled = status
|
||||||
|
end
|
||||||
|
|
||||||
|
local inVehicle
|
||||||
|
CreateThread(function()
|
||||||
|
while true do
|
||||||
|
if HUD then
|
||||||
|
local isPedUsingAnyVehicle = cache.vehicle and true or false
|
||||||
|
if isPedUsingAnyVehicle ~= inVehicle then
|
||||||
|
SendMessage('setSeatbelt', { toggled = isPedUsingAnyVehicle })
|
||||||
|
if not isPedUsingAnyVehicle and isBuckled then isBuckled = false end
|
||||||
|
inVehicle = isPedUsingAnyVehicle
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Wait(1000)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
lib.addKeybind({
|
||||||
|
name = 'seatbelt',
|
||||||
|
description = 'Toggle Seatbelt',
|
||||||
|
defaultKey = GetConvar('hud:seatbeltKey', 'B'),
|
||||||
|
onPressed = function()
|
||||||
|
if cache.vehicle then
|
||||||
|
local curVehicleClass = GetVehicleClass(cache.vehicle)
|
||||||
|
|
||||||
|
if curVehicleClass ~= 8
|
||||||
|
and curVehicleClass ~= 13
|
||||||
|
and curVehicleClass ~= 14
|
||||||
|
then
|
||||||
|
Seatbelt(not isBuckled)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
52
client/vehicle.lua
Normal file
52
client/vehicle.lua
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
local electricModels = {
|
||||||
|
[`airtug`] = true,
|
||||||
|
[`caddy`] = true,
|
||||||
|
[`caddy2`] = true,
|
||||||
|
[`caddy3`] = true,
|
||||||
|
[`cyclone`] = true,
|
||||||
|
[`cyclone2`] = true,
|
||||||
|
[`dilettante`] = true,
|
||||||
|
[`dilettante2`] = true,
|
||||||
|
[`imorgon`] = true,
|
||||||
|
[`iwagen`] = true,
|
||||||
|
[`khamelion`] = true,
|
||||||
|
[`neon`] = true,
|
||||||
|
[`omnisegt`] = true,
|
||||||
|
[`powersurge`] = true,
|
||||||
|
[`raiden`] = true,
|
||||||
|
[`rcbandito`] = true,
|
||||||
|
[`surge`] = true,
|
||||||
|
[`tezeract`] = true,
|
||||||
|
[`virtue`] = true,
|
||||||
|
[`voltic`] = true,
|
||||||
|
[`voltic2`] = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
local offVehicle, model
|
||||||
|
|
||||||
|
CreateThread(function()
|
||||||
|
while true do
|
||||||
|
if HUD then
|
||||||
|
if cache.vehicle then
|
||||||
|
model = GetEntityModel(cache.vehicle)
|
||||||
|
|
||||||
|
SendMessage('setVehicle', {
|
||||||
|
speed = {
|
||||||
|
current = GetEntitySpeed(cache.vehicle),
|
||||||
|
max = GetVehicleModelMaxSpeed(model)
|
||||||
|
},
|
||||||
|
unitsMultiplier = GetConvar('hud:unitsystem', 'imperial') == 'metric' and 3.6 or 2.236936,
|
||||||
|
fuel = GetConvar('hud:fuel', 'false') and not IsThisModelABicycle(model) and
|
||||||
|
GetVehicleFuelLevel(cache.vehicle),
|
||||||
|
electric = electricModels[model]
|
||||||
|
})
|
||||||
|
|
||||||
|
offVehicle = false
|
||||||
|
elseif not offVehicle then
|
||||||
|
SendMessage('setVehicle', false)
|
||||||
|
offVehicle = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Wait(200)
|
||||||
|
end
|
||||||
|
end)
|
||||||
53
client/voice.lua
Normal file
53
client/voice.lua
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
if GetConvar('hud:voice', 'false') == 'true' then
|
||||||
|
local service = GetConvar('hud:voiceService', 'pma-voice')
|
||||||
|
|
||||||
|
local voiceCon, voiceDisc
|
||||||
|
local isTalking, isSilent
|
||||||
|
|
||||||
|
CreateThread(function()
|
||||||
|
while true do
|
||||||
|
if HUD then
|
||||||
|
if service == 'pma-voice' then
|
||||||
|
voiceCon = MumbleIsConnected()
|
||||||
|
isTalking = NetworkIsPlayerTalking(cache.playerId)
|
||||||
|
end
|
||||||
|
|
||||||
|
if service == 'pma-voice' and voiceCon
|
||||||
|
or service == 'saltychat' and voiceCon > 0
|
||||||
|
then
|
||||||
|
if isTalking then
|
||||||
|
SendMessage('setVoice', isTalking)
|
||||||
|
isSilent = false
|
||||||
|
elseif not isSilent then
|
||||||
|
SendMessage('setVoice', isTalking)
|
||||||
|
isSilent = true
|
||||||
|
end
|
||||||
|
voiceDisc = false
|
||||||
|
elseif not voiceDisc then
|
||||||
|
SendMessage('setVoice', 'disconnected')
|
||||||
|
voiceDisc = true
|
||||||
|
isSilent = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Wait(200)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if service == 'pma-voice' then
|
||||||
|
AddEventHandler('pma-voice:setTalkingMode', function(mode)
|
||||||
|
SendMessage('setVoiceRange', mode)
|
||||||
|
end)
|
||||||
|
elseif service == 'saltychat' then
|
||||||
|
AddEventHandler('SaltyChat_PluginStateChanged', function(_voiceCon)
|
||||||
|
voiceCon = _voiceCon
|
||||||
|
end)
|
||||||
|
|
||||||
|
AddEventHandler('SaltyChat_TalkStateChanged', function(_isTalking)
|
||||||
|
isTalking = _isTalking
|
||||||
|
end)
|
||||||
|
|
||||||
|
AddEventHandler('SaltyChat_VoiceRangeChanged', function(range, index, count)
|
||||||
|
SendMessage('setVoiceRange', index)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
43
fxmanifest.lua
Normal file
43
fxmanifest.lua
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
--[[ FX Information ]]--
|
||||||
|
fx_version 'cerulean'
|
||||||
|
use_experimental_fxv2_oal 'yes'
|
||||||
|
lua54 'yes'
|
||||||
|
game 'gta5'
|
||||||
|
|
||||||
|
--[[ Resource Information ]]--
|
||||||
|
name 'xhud'
|
||||||
|
version '1.1.1'
|
||||||
|
description 'A FiveM HUD for ox_core or ESX Legacy.'
|
||||||
|
license 'MIT License'
|
||||||
|
author 'Michatec'
|
||||||
|
repository 'https://github.com/Michatec/xhud'
|
||||||
|
|
||||||
|
--[[ Manifest ]]--
|
||||||
|
dependencies {
|
||||||
|
'ox_lib'
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_scripts {
|
||||||
|
'@ox_lib/init.lua',
|
||||||
|
'shared/init.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
client_scripts {
|
||||||
|
'client/frameworks.lua',
|
||||||
|
'client/hud.lua',
|
||||||
|
'client/vehicle.lua',
|
||||||
|
'client/minimap.lua',
|
||||||
|
'client/seatbelt.lua',
|
||||||
|
'client/voice.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
server_scripts {
|
||||||
|
'server/seatbelt.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_page 'web/index.html'
|
||||||
|
|
||||||
|
files {
|
||||||
|
'web/index.html',
|
||||||
|
'web/**/*'
|
||||||
|
}
|
||||||
3
server/seatbelt.lua
Normal file
3
server/seatbelt.lua
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
if GetConvar('hud:seatbelt', 'false') == 'true' then
|
||||||
|
SetConvarReplicated('game_enableFlyThroughWindscreen', 'true')
|
||||||
|
end
|
||||||
120
shared/init.lua
Normal file
120
shared/init.lua
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
if not IsDuplicityVersion() then
|
||||||
|
HUD = false
|
||||||
|
|
||||||
|
local NuiReady = false
|
||||||
|
RegisterNUICallback('nuiReady', function(_, cb)
|
||||||
|
NuiReady = true
|
||||||
|
cb({})
|
||||||
|
end)
|
||||||
|
|
||||||
|
---Easier NUI Messages
|
||||||
|
---@param action string
|
||||||
|
---@param message any
|
||||||
|
function SendMessage(action, message)
|
||||||
|
SendNUIMessage({
|
||||||
|
action = action,
|
||||||
|
message = message
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
---Initialize HUD
|
||||||
|
function InitializeHUD()
|
||||||
|
DisplayRadar(false)
|
||||||
|
repeat Wait(100) until PlayerLoaded and NuiReady
|
||||||
|
|
||||||
|
if GetConvar('hud:circleMap', 'true') == 'true' then
|
||||||
|
RequestStreamedTextureDict('circlemap', false)
|
||||||
|
repeat Wait(100) until HasStreamedTextureDictLoaded('circlemap')
|
||||||
|
AddReplaceTexture('platform:/textures/graphics', 'radarmasksm', 'circlemap', 'radarmasksm')
|
||||||
|
|
||||||
|
SetMinimapClipType(1)
|
||||||
|
SetMinimapComponentPosition('minimap', 'L', 'B', -0.017, -0.02, 0.207, 0.32)
|
||||||
|
SetMinimapComponentPosition('minimap_mask', 'L', 'B', 0.06, 0.00, 0.132, 0.260)
|
||||||
|
SetMinimapComponentPosition('minimap_blur', 'L', 'B', 0.005, -0.05, 0.166, 0.257)
|
||||||
|
else
|
||||||
|
SetMinimapComponentPosition('minimap', 'L', 'B', 0.0, -0.035, 0.18, 0.21)
|
||||||
|
SetMinimapComponentPosition('minimap_mask', 'L', 'B', 0.0, -0.05, 0.132, 0.19)
|
||||||
|
SetMinimapComponentPosition('minimap_blur', 'L', 'B', -0.025, -0.015, 0.3, 0.25)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
SetRadarBigmapEnabled(true, false)
|
||||||
|
SetRadarBigmapEnabled(false, false)
|
||||||
|
Wait(500)
|
||||||
|
|
||||||
|
if IsPedSwimming(cache.ped) then
|
||||||
|
lib.notify({
|
||||||
|
id = 'xhud:swimming',
|
||||||
|
title = 'HUD',
|
||||||
|
description = 'Looks like you are swimming, please don\'t go underwater while the HUD is loading.',
|
||||||
|
type = 'inform',
|
||||||
|
duration = 5000
|
||||||
|
})
|
||||||
|
local timer = 5000
|
||||||
|
while not maxUnderwaterTime do
|
||||||
|
Wait(1000)
|
||||||
|
timer -= 1000
|
||||||
|
if not IsPedSwimmingUnderWater(cache.ped) then
|
||||||
|
maxUnderwaterTime = timer == 0 and GetPlayerUnderwaterTimeRemaining(cache.playerId) or nil
|
||||||
|
else
|
||||||
|
timer = 5000
|
||||||
|
lib.notify({
|
||||||
|
id = 'xhud:initializing',
|
||||||
|
title = 'HUD',
|
||||||
|
description = 'Please stay on the surface for at least 5 seconds!',
|
||||||
|
type = 'inform',
|
||||||
|
duration = 5000
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
maxUnderwaterTime = GetPlayerUnderwaterTimeRemaining(cache.playerId)
|
||||||
|
end
|
||||||
|
|
||||||
|
SendMessage('setPlayerId', cache.serverId)
|
||||||
|
|
||||||
|
if GetConvar('hud:logo', 'true') == 'true' then
|
||||||
|
SendMessage('setLogo')
|
||||||
|
end
|
||||||
|
|
||||||
|
HUD = true
|
||||||
|
SendMessage('toggleHud', HUD)
|
||||||
|
end
|
||||||
|
|
||||||
|
AddEventHandler('onResourceStart', function(resourceName)
|
||||||
|
if cache.resource ~= resourceName then return end
|
||||||
|
InitializeHUD()
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Commands
|
||||||
|
lib.addCommand('togglehud', {
|
||||||
|
help = 'Toggle the HUD visibility',
|
||||||
|
}, function()
|
||||||
|
HUD = not HUD
|
||||||
|
SendMessage('toggleHud', HUD)
|
||||||
|
lib.notify({
|
||||||
|
id = 'xhud:toggle',
|
||||||
|
title = 'HUD',
|
||||||
|
description = HUD and 'HUD enabled' or 'HUD disabled',
|
||||||
|
type = 'inform',
|
||||||
|
duration = 2000
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
lib.addCommand('reloadhud', {
|
||||||
|
help = 'Reload the HUD',
|
||||||
|
}, function()
|
||||||
|
InitializeHUD()
|
||||||
|
lib.notify({
|
||||||
|
id = 'xhud:reload',
|
||||||
|
title = 'HUD',
|
||||||
|
description = 'HUD reloaded successfully',
|
||||||
|
type = 'inform',
|
||||||
|
duration = 2000
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
if GetConvar('hud:versioncheck', 'true') == 'true' then
|
||||||
|
lib.versionCheck('michatec/xhud')
|
||||||
|
end
|
||||||
|
end
|
||||||
BIN
stream/circlemap.ytd
Normal file
BIN
stream/circlemap.ytd
Normal file
Binary file not shown.
BIN
web/assets/images/logo.png
Normal file
BIN
web/assets/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
web/assets/sounds/buckle.ogg
Normal file
BIN
web/assets/sounds/buckle.ogg
Normal file
Binary file not shown.
BIN
web/assets/sounds/unbuckle.ogg
Normal file
BIN
web/assets/sounds/unbuckle.ogg
Normal file
Binary file not shown.
80
web/index.html
Normal file
80
web/index.html
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||||
|
<title>xHUD</title>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
||||||
|
integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="Container">
|
||||||
|
<div id="IconsContainer">
|
||||||
|
<div id="Icons">
|
||||||
|
<div id="VoiceIndicator" class="Icon">
|
||||||
|
<i id="VoiceIcon" class="fas fa-times"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="HealthIndicator" class="Icon">
|
||||||
|
<i id="HealthIcon" class="fas fa-heart"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="ArmourIndicator" class="Icon">
|
||||||
|
<i id="ArmourIcon" class="fas fa-shield-alt"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="StaminaIndicator" class="Icon">
|
||||||
|
<i id="StaminaIcon" class="fas fa-running"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="HungerIndicator" class="Icon">
|
||||||
|
<i id="HungerIcon" class="fas fa-hamburger"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="ThirstIndicator" class="Icon">
|
||||||
|
<i id="ThirstIcon" class="fas fa-tint"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="StressIndicator" class="Icon">
|
||||||
|
<i id="StressIcon" class="fas fa-brain"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="OxygenIndicator" class="Icon">
|
||||||
|
<i id="OxygenIcon" class="fas fa-lungs"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="FuelIndicator" class="Icon">
|
||||||
|
<i id="FuelIcon" class="fas fa-gas-pump"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="SpeedIndicator" class="Icon">
|
||||||
|
<i id="SpeedIcon" class="fas fa-tachometer-alt"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<i id="SeatbeltIcon" class="fas fa-user-slash outerIcon"></i>
|
||||||
|
|
||||||
|
<div id="ID" class="outerIcon"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="Logo">
|
||||||
|
<img src="assets/images/logo.png" alt="xHUD Logo" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<audio id="buckle" src="assets/sounds/buckle.ogg" preload></audio>
|
||||||
|
<audio id="unbuckle" src="assets/sounds/unbuckle.ogg" preload></audio>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/progressbar.js/0.6.1/progressbar.min.js"
|
||||||
|
integrity="sha512-7IoDEsIJGxz/gNyJY/0LRtS45wDSvPFXGPuC7Fo4YueWMNOmWKMAllEqo2Im3pgOjeEwsOoieyliRgdkZnY0ow=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<script type="module" src="js/listener.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
66
web/js/circles.js
Normal file
66
web/js/circles.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
export default {
|
||||||
|
HealthIndicator: new ProgressBar.Circle("#HealthIndicator", {
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
ArmourIndicator: new ProgressBar.Circle("#ArmourIndicator", {
|
||||||
|
color: "rgb(0, 140, 255)",
|
||||||
|
trailColor: "rgb(35, 35, 35)",
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
StaminaIndicator: new ProgressBar.Circle("#StaminaIndicator", {
|
||||||
|
color: "rgb(255, 255, 204)",
|
||||||
|
trailColor: "rgb(35, 35, 35)",
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
HungerIndicator: new ProgressBar.Circle("#HungerIndicator", {
|
||||||
|
color: "rgb(255, 164, 59)",
|
||||||
|
trailColor: "rgb(35, 35, 35)",
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
ThirstIndicator: new ProgressBar.Circle("#ThirstIndicator", {
|
||||||
|
color: "rgb(0, 140, 170)",
|
||||||
|
trailColor: "rgb(35, 35, 35)",
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
StressIndicator: new ProgressBar.Circle("#StressIndicator", {
|
||||||
|
color: "rgb(255, 74, 104)",
|
||||||
|
trailColor: "rgb(35, 35, 35)",
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
OxygenIndicator: new ProgressBar.Circle("#OxygenIndicator", {
|
||||||
|
trailColor: "rgb(35, 35, 35)",
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
SpeedIndicator: new ProgressBar.Circle("#SpeedIndicator", {
|
||||||
|
color: "rgb(255, 255, 255)",
|
||||||
|
trailColor: "rgb(35, 35, 35)",
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
FuelIndicator: new ProgressBar.Circle("#FuelIndicator", {
|
||||||
|
trailColor: "rgb(35, 35, 35)",
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 600,
|
||||||
|
}),
|
||||||
|
VoiceIndicator: new ProgressBar.Circle("#VoiceIndicator", {
|
||||||
|
strokeWidth: 13,
|
||||||
|
trailWidth: 13,
|
||||||
|
duration: 100,
|
||||||
|
}),
|
||||||
|
};
|
||||||
251
web/js/listener.js
Normal file
251
web/js/listener.js
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
"use strict";
|
||||||
|
import Circle from "./circles.js";
|
||||||
|
|
||||||
|
window.onload = (event) => {
|
||||||
|
fetch(`https://${GetParentResourceName()}/nuiReady`);
|
||||||
|
|
||||||
|
const Container = document.getElementById("Container");
|
||||||
|
const Logo = document.getElementById("Logo");
|
||||||
|
const ID = document.getElementById("ID");
|
||||||
|
|
||||||
|
const Speed = document.getElementById("SpeedIndicator");
|
||||||
|
const Fuel = document.getElementById("FuelIndicator");
|
||||||
|
const Voice = document.getElementById("VoiceIndicator");
|
||||||
|
const Armour = document.getElementById("ArmourIndicator");
|
||||||
|
const Stamina = document.getElementById("StaminaIndicator");
|
||||||
|
const Oxygen = document.getElementById("OxygenIndicator");
|
||||||
|
const Health = document.getElementById("HealthIndicator");
|
||||||
|
const Hunger = document.getElementById("HungerIndicator");
|
||||||
|
const Thirst = document.getElementById("ThirstIndicator");
|
||||||
|
const Stress = document.getElementById("StressIndicator");
|
||||||
|
|
||||||
|
const HealthIcon = document.getElementById("HealthIcon");
|
||||||
|
const SpeedIcon = document.getElementById("SpeedIcon");
|
||||||
|
const VoiceIcon = document.getElementById("VoiceIcon");
|
||||||
|
const OxygenIcon = document.getElementById("OxygenIcon");
|
||||||
|
const FuelIcon = document.getElementById("FuelIcon");
|
||||||
|
const HungerIcon = document.getElementById("HungerIcon");
|
||||||
|
const ThirstIcon = document.getElementById("ThirstIcon");
|
||||||
|
const StressIcon = document.getElementById("StressIcon");
|
||||||
|
|
||||||
|
const Seatbelt = document.getElementById("SeatbeltIcon");
|
||||||
|
const Buckle = document.getElementById("buckle");
|
||||||
|
const Unbuckle = document.getElementById("unbuckle");
|
||||||
|
|
||||||
|
Circle.VoiceIndicator.animate(0.66);
|
||||||
|
|
||||||
|
window.addEventListener("message", function (event) {
|
||||||
|
let action = event.data.action;
|
||||||
|
let data = event.data.message;
|
||||||
|
|
||||||
|
if (action == "toggleHud") {
|
||||||
|
Container.style.display = data ? "flex" : "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setLogo") {
|
||||||
|
Logo.style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setPlayerId") {
|
||||||
|
if (data) {
|
||||||
|
ID.style.display = "block";
|
||||||
|
ID.textContent = "#" + data;
|
||||||
|
} else {
|
||||||
|
ID.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setHealth") {
|
||||||
|
Health.style.display = "block";
|
||||||
|
|
||||||
|
let health = (data.current - 100) / (data.max - 100);
|
||||||
|
health < 0 && (health = 0);
|
||||||
|
|
||||||
|
if (health) {
|
||||||
|
HealthIcon.classList.remove("fa-skull");
|
||||||
|
HealthIcon.classList.add("fa-heart");
|
||||||
|
} else {
|
||||||
|
HealthIcon.classList.remove("fa-heart");
|
||||||
|
HealthIcon.classList.add("fa-skull");
|
||||||
|
}
|
||||||
|
|
||||||
|
Circle.HealthIndicator.trail.setAttribute(
|
||||||
|
"stroke",
|
||||||
|
health ? "rgb(35, 35, 35)" : "rgb(255, 0, 0)"
|
||||||
|
);
|
||||||
|
Circle.HealthIndicator.path.setAttribute(
|
||||||
|
"stroke",
|
||||||
|
health ? "rgb(0, 255, 100)" : "rgb(255, 0, 0)"
|
||||||
|
);
|
||||||
|
Circle.HealthIndicator.animate(health);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setArmour") {
|
||||||
|
Armour.style.display = "block";
|
||||||
|
Circle.ArmourIndicator.animate(data / 100, function () {
|
||||||
|
Armour.style.display = data == 0 && "none";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setStamina") {
|
||||||
|
if (data) {
|
||||||
|
Stamina.style.display = "block";
|
||||||
|
|
||||||
|
let stamina = data.current / data.max;
|
||||||
|
stamina < 0 && (stamina = 0);
|
||||||
|
stamina < 0.1 && StaminaIcon.classList.toggle("flash");
|
||||||
|
|
||||||
|
Circle.StaminaIndicator.path.setAttribute(
|
||||||
|
"stroke",
|
||||||
|
stamina < 0.1 ? "rgb(255, 0, 0)" : "rgb(255, 255, 200)"
|
||||||
|
);
|
||||||
|
Circle.StaminaIndicator.animate(stamina);
|
||||||
|
} else {
|
||||||
|
Circle.StaminaIndicator.animate(1, function () {
|
||||||
|
Stamina.style.display = "none";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setOxygen") {
|
||||||
|
if (data) {
|
||||||
|
Oxygen.style.display = "block";
|
||||||
|
|
||||||
|
let oxygen = data.current / data.max;
|
||||||
|
oxygen < 0 && (oxygen = 0);
|
||||||
|
oxygen < 0.1 && OxygenIcon.classList.toggle("flash");
|
||||||
|
|
||||||
|
Circle.OxygenIndicator.path.setAttribute(
|
||||||
|
"stroke",
|
||||||
|
oxygen < 0.1 ? "rgb(255, 0, 0)" : "rgb(0, 140, 255)"
|
||||||
|
);
|
||||||
|
Circle.OxygenIndicator.animate(oxygen);
|
||||||
|
} else {
|
||||||
|
Circle.OxygenIndicator.animate(1, function () {
|
||||||
|
Oxygen.style.display = "none";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setVehicle") {
|
||||||
|
if (data) {
|
||||||
|
Speed.style.display = "block";
|
||||||
|
|
||||||
|
let speed = data.speed.current * data.unitsMultiplier;
|
||||||
|
let maxSpeed = data.speed.max * data.unitsMultiplier;
|
||||||
|
let percSpeed = (speed / maxSpeed) * 0.7;
|
||||||
|
let fuel = data.fuel && data.fuel / 100;
|
||||||
|
|
||||||
|
percSpeed > 1 && (percSpeed = 1);
|
||||||
|
percSpeed >= 0.01 && SpeedIcon.classList.remove("fa-tachometer-alt");
|
||||||
|
percSpeed >= 0.01 && (SpeedIcon.textContent = Math.floor(speed));
|
||||||
|
percSpeed < 0.01 && SpeedIcon.classList.add("fa-tachometer-alt");
|
||||||
|
percSpeed < 0.01 && (SpeedIcon.textContent = "");
|
||||||
|
|
||||||
|
if (data.electric == true) {
|
||||||
|
FuelIcon.classList.remove("fa-gas-pump");
|
||||||
|
FuelIcon.classList.add("fa-bolt");
|
||||||
|
fuel = 1;
|
||||||
|
} else {
|
||||||
|
FuelIcon.classList.remove("fa-bolt");
|
||||||
|
FuelIcon.classList.add("fa-gas-pump");
|
||||||
|
}
|
||||||
|
|
||||||
|
Fuel.style.display = fuel !== false ? "block" : "none";
|
||||||
|
fuel <= 0.15 && FuelIcon.classList.toggle("flash");
|
||||||
|
Circle.FuelIndicator.path.setAttribute(
|
||||||
|
"stroke",
|
||||||
|
fuel > 0.15 ? "rgb(255, 255, 255)" : "rgb(255, 0, 0)"
|
||||||
|
);
|
||||||
|
|
||||||
|
Circle.SpeedIndicator.animate(percSpeed);
|
||||||
|
Circle.FuelIndicator.animate(fuel);
|
||||||
|
} else {
|
||||||
|
Circle.SpeedIndicator.animate(0, function () {
|
||||||
|
Speed.style.display = "none";
|
||||||
|
});
|
||||||
|
Circle.FuelIndicator.animate(0, function () {
|
||||||
|
Fuel.style.display = "none";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setVoice") {
|
||||||
|
Voice.style.display = "block";
|
||||||
|
if (data == "disconnected") {
|
||||||
|
VoiceIcon.classList.remove("fa-microphone");
|
||||||
|
VoiceIcon.classList.add("fa-times");
|
||||||
|
Circle.VoiceIndicator.path.setAttribute("stroke", "rgb(255, 0, 0)");
|
||||||
|
Circle.VoiceIndicator.trail.setAttribute("stroke", "rgb(255, 0, 0)");
|
||||||
|
} else {
|
||||||
|
VoiceIcon.classList.remove("fa-times");
|
||||||
|
VoiceIcon.classList.add("fa-microphone");
|
||||||
|
Circle.VoiceIndicator.path.setAttribute(
|
||||||
|
"stroke",
|
||||||
|
data ? "rgb(255, 255, 0)" : "rgb(169, 169, 169)"
|
||||||
|
);
|
||||||
|
Circle.VoiceIndicator.trail.setAttribute("stroke", "rgb(35, 35, 35)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setVoiceRange") {
|
||||||
|
switch (data) {
|
||||||
|
case 0:
|
||||||
|
data = 15;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
data = 33;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
data = 66;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
data = 100;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
data = 33;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Circle.VoiceIndicator.animate(data / 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "status") {
|
||||||
|
Hunger.style.display = "block";
|
||||||
|
Thirst.style.display = "block";
|
||||||
|
Stress.style.display = data.stress > 5 && "block";
|
||||||
|
|
||||||
|
data.hunger < 15 && HungerIcon.classList.toggle("flash");
|
||||||
|
data.thirst < 15 && ThirstIcon.classList.toggle("flash");
|
||||||
|
data.stress > 50 && StressIcon.classList.toggle("flash");
|
||||||
|
|
||||||
|
Circle.HungerIndicator.animate(data.hunger / 100);
|
||||||
|
Circle.ThirstIndicator.animate(data.thirst / 100);
|
||||||
|
Circle.StressIndicator.animate(data.stress / 100, function () {
|
||||||
|
Stress.style.display = data.stress <= 5 && "none";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "setSeatbelt") {
|
||||||
|
Seatbelt.style.display = data.toggled ? "block" : "none";
|
||||||
|
Seatbelt.style.color = data.buckled
|
||||||
|
? "rgb(0, 255, 100)"
|
||||||
|
: "rgb(255, 100, 100)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "playSound") {
|
||||||
|
switch (data) {
|
||||||
|
case "unbuckle":
|
||||||
|
Unbuckle.volume = 0.2;
|
||||||
|
Unbuckle.play();
|
||||||
|
break;
|
||||||
|
case "buckle":
|
||||||
|
Buckle.volume = 0.2;
|
||||||
|
Buckle.play();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
97
web/style.css
Normal file
97
web/style.css
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#Container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#IconsContainer {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#Icons {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
margin: 20px 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Icon {
|
||||||
|
position: relative;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgb(50, 50, 50);
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Icon i {
|
||||||
|
color: white;
|
||||||
|
position: absolute;
|
||||||
|
font-size: 16px;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Customisations */
|
||||||
|
|
||||||
|
#SpeedIcon:not(.fa-tachometer-alt) {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ID {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outerIcon {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
height: 50px;
|
||||||
|
text-shadow: 1px 1px 10px #000;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 50px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo */
|
||||||
|
|
||||||
|
#Logo {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 40px;
|
||||||
|
max-width: 128px;
|
||||||
|
opacity: 0.8;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
|
||||||
|
.flash {
|
||||||
|
-webkit-animation: flash 1s;
|
||||||
|
animation: flash 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flash {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user