This stores the position, rotation, and scale of every object. High-quality scripts use native GTA V objects (no custom models needed) to ensure stability.
fx_version 'cerulean'
game 'gta5'
client_script 'client.lua'
-- Configuration
local GateCoords = vector3(451.45, -1019.5, 28.5) -- Example: Mission Row Police Parking
local KeypadCoords = vector3(453.8, -1019.3, 28.5)
local GateModel = `prop_gate_airport_01` -- The model of the gate
local KeypadModel = `prop_keypad_01` -- Keypad prop
local GateHeading = 90.0 -- Rotation of the gate
local OpenOffset = 5.0 -- How far the gate moves to the right
-- Variables
local gateObj = nil
local keypadObj = nil
local isGateOpen = false
local isMoving = false
-- Create the objects when resource starts
CreateThread(function()
-- Load models
RequestModel(GateModel)
RequestModel(KeypadModel)
while not HasModelLoaded(GateModel) or not HasModelLoaded(KeypadModel) do
Wait(100)
end
-- Spawn Gate
gateObj = CreateObject(GateModel, GateCoords.x, GateCoords.y, GateCoords.z, false, false, false)
SetEntityHeading(gateObj, GateHeading)
FreezeEntityPosition(gateObj, true)
-- Spawn Keypad
keypadObj = CreateObject(KeypadModel, KeypadCoords.x, KeypadCoords.y, KeypadCoords.z, false, false, false)
SetEntityHeading(keypadObj, GateHeading - 90.0) -- Face the keypad towards the player
-- Cleanup models from memory
SetModelAsNoLongerNeeded(GateModel)
SetModelAsNoLongerNeeded(KeypadModel)
end)
-- Main Thread (Interaction Loop)
CreateThread(function()
while true do
Wait(0)
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
local dist = #(coords - KeypadCoords)
-- If player is close to keypad
if dist < 2.0 then
-- Draw Marker (or you can use TextUI here)
DrawMarker(2, KeypadCoords.x, KeypadCoords.y, KeypadCoords.z + 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.3, 0.3, 255, 255, 255, 165, 0, 0, 0, 0)
-- Show Help Text
BeginTextCommandDisplayHelp("STRING")
AddTextComponentSubstringPlayerName("Press ~INPUT_CONTEXT~ to operate gate") -- 'E' key
EndTextCommandDisplayHelp(0, false, true, -1)
-- Check for Key Press (E / INPUT_CONTEXT)
if IsControlJustPressed(1, 51) then
if not isMoving then
ToggleGate()
end
end
else
Wait(500) -- Optimize loop if far away
end
end
end)
-- Function to handle Gate Movement
function ToggleGate()
isMoving = true -- Lock interaction during animation
-- Play Sound (Client side)
-- You can replace this with native sounds like "DOOR_HEIST_METAL_GATE_OPEN"
PlaySoundFromCoord(-1, "Beep_Red", KeypadCoords.x, KeypadCoords.y, KeypadCoords.z, "DLC_HEIST_HACKING_SNAKE_SOUNDS", false, 5.0, false)
-- Logic for Open/Close
local targetX = GateCoords.x
local targetY = GateCoords.y
local targetZ = GateCoords.z
if not isGateOpen then
-- Calculate Open Position (Slides sideways based on heading)
-- Simple logic: Move on X axis for this example
targetX = GateCoords.x + OpenOffset
isGateOpen = true
else
-- Return to start
isGateOpen = false
end
-- Smooth Animation Loop
local startTime = GetGameTimer()
local duration = 2000 -- 2 seconds to open
local startX, startY, startZ = GetEntityCoords(gateObj)
while GetGameTimer() - startTime < duration do
local progress = (GetGameTimer() - startTime) / duration
local currX = startX + (targetX - startX) * progress
local currY = startY + (targetY - startY) * progress
SetEntityCoords(gateObj, currX, currY, startZ)
Wait(0)
end
-- Ensure final position is exact
SetEntityCoords(gateObj, targetX, targetY, startZ)
isMoving = false
end
-- Cleanup on Resource Stop (Very Important!)
AddEventHandler('onResourceStop', function(resourceName)
if GetCurrentResourceName() == resourceName then
if DoesEntityExist(gateObj) then DeleteEntity(gateObj) end
if DoesEntityExist(keypadObj) then DeleteEntity(keypadObj) end
end
end)
for _,ent in pairs(spawnedEntities) do
if DoesEntityExist(ent) then
DeleteObject(ent)
end
end
spawnedEntities = {}