Parent : [[INDEX-FIVEM-GAMEPLAY]]
FiveM - Visual Effects State Machine (Drunk) : niveaux, AnimSet, TimecycleModifier, reset
Problème
Les effets visuels (ivresse, drogue, fatigue) doivent être progressifs, avec plusieurs niveaux, et doivent être complètement réversibles.
Solution
Machine à états visuels avec 3 niveaux d'ivresse (slightly/moderate/very drunk), chargement d'AnimSet, TimecycleModifier, ScreenFade, et fonction de reset complet (Reality).
local IsAlreadyDrunk = false
local DrunkLevel = -1
function Drunk(level, start)
CreateThread(function()
local playerPed = PlayerPedId()
if start then
DoScreenFadeOut(800)
Wait(1000)
end
if level == 0 then
RequestAnimSet("move_m@drunk@slightlydrunk")
while not HasAnimSetLoaded("move_m@drunk@slightlydrunk") do Wait(0) end
SetPedMovementClipset(playerPed, "move_m@drunk@slightlydrunk", true)
elseif level == 1 then
RequestAnimSet("move_m@drunk@moderatedrunk")
while not HasAnimSetLoaded("move_m@drunk@moderatedrunk") do Wait(0) end
SetPedMovementClipset(playerPed, "move_m@drunk@moderatedrunk", true)
elseif level == 2 then
RequestAnimSet("move_m@drunk@verydrunk")
while not HasAnimSetLoaded("move_m@drunk@verydrunk") do Wait(0) end
SetPedMovementClipset(playerPed, "move_m@drunk@verydrunk", true)
end
SetTimecycleModifier("spectator5")
SetPedMotionBlur(playerPed, true)
SetPedIsDrunk(playerPed, true)
if start then
DoScreenFadeIn(800)
end
end)
end
function Reality()
CreateThread(function()
local playerPed = PlayerPedId()
DoScreenFadeOut(800)
Wait(1000)
ClearTimecycleModifier()
ResetScenarioTypesEnabled()
ResetPedMovementClipset(playerPed, 0)
SetPedIsDrunk(playerPed, false)
SetPedMotionBlur(playerPed, false)
DoScreenFadeIn(800)
end)
end
-- Trigger via statut ESX
AddEventHandler('esx_status:loaded', function(status)
TriggerEvent('esx_status:registerStatus', 'drunk', 0, '#8F15A5',
function(status)
if status.val > 0 then
return true
else
return false
end
end,
function(status)
status.remove(1500) -- Se dissipe lentement
end
)
end)
AddEventHandler('esx_status:onTick', function(status)
if status.val > 500000 then
Drunk(2, false)
elseif status.val > 250000 then
Drunk(1, false)
elseif status.val > 100000 then
Drunk(0, false)
else
Reality()
end
end)
Pourquoi
- ScreenFade masque le changement brusque d'effets visuels
ResetPedMovementClipsetetClearTimecycleModifiergarantissent un retour propre à la normal- Les niveaux progressifs créent une expérience réaliste
Quand l'utiliser
- Systèmes de consommation (alcool, drogue)
- Effets de blessure (fatigue, saignement)
- Environnement (tempête de sable, gaz)
Quand NE PAS l'utiliser
- Effets permanents (tatouages, cicatrices) → pas de reset
- Si le ScreenFade est trop disruprif pour du gameplay compétitif
Exemples
Correct
-- Gestion complète avec garde-fou
function ApplyEffect(level, effectType)
if level < 0 or level > 2 then return end
if IsAlreadyDrunk and DrunkLevel == level then return end
IsAlreadyDrunk = true
DrunkLevel = level
Drunk(level, true)
end
function ClearAllEffects()
if not IsAlreadyDrunk then return end
IsAlreadyDrunk = false
DrunkLevel = -1
Reality()
end
Incorrect
-- Pas de reset complet → effets qui persistent après respawn
RegisterNetEvent('drug:take')
AddEventHandler('drug:take', function()
SetTimecycleModifier("spectator5")
SetPedMovementClipset(PlayerPedId(), "move_m@drunk@verydrunk", true)
-- JAMAIS reset → effet permanent
end)
Références
- esx_optionalneeds/client/main.lua L1-77