@@ -138,7 +138,7 @@ AddStateBagChangeHandler("VehicleProperties", nil, function(bagName, _, value)
138138 end
139139
140140 local tries = 0
141-
141+
142142 while not NetworkDoesEntityExistWithNetworkId (netId ) do
143143 Wait (200 )
144144 tries = tries + 1
@@ -499,49 +499,132 @@ RegisterNetEvent("esx:tpm", function()
499499 end )
500500end )
501501
502- local noclip = false
503- local noclip_pos = vector3 (0 , 0 , 70 )
504- local heading = 0
502+ local noclipActive = false
503+ local noclipEntity = nil
504+ local followCamMode = true
505+ local speedIndex = 1
506+ local currentSpeed = 0.2
507+ local yOffset , zOffset , hOffset = 0.5 , 0.2 , 3
508+
509+ -- cached config values
510+ local controls = Config .Noclip .controls
511+ local speedOptions = Config .Noclip .speeds
512+
513+ --- Toggles noclip state for the given entity
514+ --- @param entity number ? Entity handle to apply noclip settings to
515+ --- @param isActive boolean Whether noclip should be enabled or disabled
516+ local function toggleNoclip (entity , isActive )
517+ if not entity or not DoesEntityExist (entity ) then return end
518+
519+ SetEntityAlpha (entity , isActive and 102 or 255 , false )
520+ SetEntityCollision (entity , not isActive , not isActive )
521+ FreezeEntityPosition (entity , isActive )
522+ SetEntityInvincible (entity , isActive )
523+ SetEntityVisible (entity , not isActive , isActive )
505524
506- local function noclipThread ()
507- while noclip do
508- SetEntityCoordsNoOffset (ESX .PlayerData .ped , noclip_pos .x , noclip_pos .y , noclip_pos .z , false , false , true )
525+ local ped = ESX .PlayerData .ped
526+ SetEveryoneIgnorePlayer (ped , isActive )
527+ SetPoliceIgnorePlayer (ped , isActive )
528+ LocalPlayer .state :set (' inNoclip' , isActive , true )
529+ end
509530
510- if IsControlPressed (1 , 34 ) then
511- heading = heading + 1.5
512- if heading > 360 then
513- heading = 0
514- end
531+ local function cycleSpeed ()
532+ if not noclipActive then return end
515533
516- SetEntityHeading (ESX .PlayerData .ped , heading )
517- end
534+ speedIndex = speedIndex % # speedOptions + 1
535+ currentSpeed = speedOptions [speedIndex ]
536+ ESX .ShowNotification (TranslateCap (" noclip_new_speed" , currentSpeed ))
537+ end
518538
519- if IsControlPressed (1 , 9 ) then
520- heading = heading - 1.5
521- if heading < 0 then
522- heading = 360
523- end
539+ local function handleMovement ()
540+ if not noclipEntity or not DoesEntityExist (noclipEntity ) then return end
524541
525- SetEntityHeading (ESX .PlayerData .ped , heading )
526- end
542+ local yMove , zMove = 0.0 , 0.0
543+ local isForward = false
544+ local hasMovement = false
527545
528- if IsControlPressed (1 , 8 ) then
529- noclip_pos = GetOffsetFromEntityInWorldCoords (ESX .PlayerData .ped , 0.0 , 1.0 , 0.0 )
530- end
546+ if IsDisabledControlPressed (0 , controls .forward ) then
547+ yMove = yOffset
548+ isForward = true
549+ hasMovement = true
550+ elseif IsDisabledControlPressed (0 , controls .backward ) then
551+ yMove = - yOffset
552+ hasMovement = true
553+ end
531554
532- if IsControlPressed (1 , 32 ) then
533- noclip_pos = GetOffsetFromEntityInWorldCoords (ESX .PlayerData .ped , 0.0 , - 1.0 , 0.0 )
555+ if not followCamMode then
556+ if IsDisabledControlPressed (0 , controls .up ) then
557+ zMove = zOffset
558+ hasMovement = true
559+ elseif IsDisabledControlPressed (0 , controls .down ) then
560+ zMove = - zOffset
561+ hasMovement = true
534562 end
535563
536- if IsControlPressed (1 , 27 ) then
537- noclip_pos = GetOffsetFromEntityInWorldCoords (ESX .PlayerData .ped , 0.0 , 0.0 , 1.0 )
564+ if IsDisabledControlPressed (0 , controls .left ) then
565+ SetEntityHeading (noclipEntity , GetEntityHeading (noclipEntity ) + hOffset )
566+ elseif IsDisabledControlPressed (0 , controls .right ) then
567+ SetEntityHeading (noclipEntity , GetEntityHeading (noclipEntity ) - hOffset )
538568 end
539-
540- if IsControlPressed (1 , 173 ) then
541- noclip_pos = GetOffsetFromEntityInWorldCoords (ESX .PlayerData .ped , 0.0 , 0.0 , - 1.0 )
569+ else
570+ if hasMovement then
571+ local pitch = GetGameplayCamRelativePitch ()
572+ zMove = isForward and (pitch * 0.01 ) or (pitch * - 0.01 )
542573 end
543- Wait (0 )
544574 end
575+
576+ if not hasMovement then return end
577+
578+ local speedMult = currentSpeed + 0.3
579+
580+ local heading = GetEntityHeading (noclipEntity )
581+ local newPos = GetOffsetFromEntityInWorldCoords (noclipEntity , 0.0 , yMove * speedMult , zMove * speedMult )
582+
583+ SetEntityVelocity (noclipEntity , 0.0 , 0.0 , 0.0 )
584+ SetEntityRotation (noclipEntity , 0.0 , 0.0 , 0.0 , 0 , false )
585+
586+ if followCamMode then
587+ SetEntityHeading (noclipEntity , GetGameplayCamRelativeHeading ())
588+ else
589+ SetEntityHeading (noclipEntity , heading )
590+ end
591+
592+ SetEntityCoordsNoOffset (noclipEntity , newPos .x , newPos .y , newPos .z , true , true , true )
593+ end
594+
595+ local function noclipThread ()
596+ CreateThread (function ()
597+ local allowedKeys = Config .Noclip .allowedKeys
598+ local switchKey = Config .Noclip .controls .switchMode
599+ local lastToggleTime = 0
600+
601+ while noclipActive do
602+ local currentTime = GetGameTimer ()
603+
604+ DisableAllControlActions (0 )
605+
606+ for i = 1 , # allowedKeys do
607+ local key = allowedKeys [i ]
608+ EnableControlAction (key [1 ], key [2 ], true )
609+ end
610+
611+ if IsDisabledControlJustPressed (0 , switchKey ) then
612+ followCamMode = not followCamMode
613+ ESX .ShowNotification (TranslateCap (" noclip_mode_toggled" , followCamMode and Translate (" enabled" ) or Translate (" disabled" )))
614+ Wait (100 )
615+ end
616+
617+ SetLocalPlayerVisibleLocally (true );
618+ handleMovement ()
619+
620+ if currentTime - lastToggleTime >= 1000 then
621+ toggleNoclip (noclipEntity , true )
622+ lastToggleTime = currentTime
623+ end
624+
625+ Wait (0 )
626+ end
627+ end )
545628end
546629
547630RegisterNetEvent (" esx:noclip" , function ()
@@ -550,24 +633,28 @@ RegisterNetEvent("esx:noclip", function()
550633 return
551634 end
552635
553- if not noclip then
554- noclip_pos = GetEntityCoords (ESX .PlayerData .ped , false )
555- heading = GetEntityHeading (ESX .PlayerData .ped )
636+ if noclipActive then
637+ noclipActive = false
638+ toggleNoclip (noclipEntity , false )
639+ return
556640 end
557641
558- noclip = not noclip
559- if noclip then
560- CreateThread ( noclipThread )
561- end
642+ noclipActive = true
643+ noclipEntity = ESX . PlayerData . vehicle or ESX . PlayerData . ped
644+ toggleNoclip ( noclipEntity , true )
645+ noclipThread ()
562646
563- if noclip then
647+ if noclipActive then
564648 ESX .ShowNotification (TranslateCap (" noclip_message" , Translate (" enabled" )), " success" )
565649 else
566650 ESX .ShowNotification (TranslateCap (" noclip_message" , Translate (" disabled" )), " error" )
567651 end
568652 end )
569653end )
570654
655+ -- cycling speed
656+ ESX .RegisterInput (' cyclenoclipspeed' , ' Cycle Noclip Speed' , ' keyboard' , Config .Noclip .controls .cycleNoclipSpeed , cycleSpeed )
657+
571658RegisterNetEvent (" esx:killPlayer" , function ()
572659 SetEntityHealth (ESX .PlayerData .ped , 0 )
573660end )
@@ -598,7 +685,7 @@ ESX.RegisterClientCallback("esx:GetVehicleType", function(cb, model)
598685end )
599686
600687ESX .SecureNetEvent (' esx:updatePlayerData' , function (key , val )
601- ESX .SetPlayerData (key , val )
688+ ESX .SetPlayerData (key , val )
602689end )
603690
604691--- @param command string
0 commit comments