This commit is contained in:
2026-02-15 18:47:56 +01:00
commit 596d70e72f
19 changed files with 1099 additions and 0 deletions

60
client/frameworks.lua Normal file
View 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
View 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
View 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
View 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
View 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
View 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