-- Base-tier elevator: floor-select teleport menu (NUI, no dependencies). -- Runs only while the standalone layer is armed; the scripts pack's animated -- elevator takes over when it starts. local C = Config.Standalone local E = C.elevator if not E or not E.enabled then return end local menuOpen = false local function closeMenu() if not menuOpen then return end menuOpen = false SetNuiFocus(false, false) SendNUIMessage({ action = 'close' }) end local function openMenu(current) local floors = {} for i, f in ipairs(E.floors) do floors[i] = f.label end menuOpen = true SetNuiFocus(true, true) SendNUIMessage({ action = 'open', title = E.title, floors = floors, current = current }) end -- shaft interior streamed in? (mirrors validInteriorAt in standalone/client.lua) local function shaftInteriorLoaded() local id = GetInteriorAtCoords(E.probe.x, E.probe.y, E.probe.z) return id ~= 0 and IsValidInterior(id) end -- nearest floor point within interactRadius, or nil local function nearestFloor() local pc = GetEntityCoords(PlayerPedId()) local best, bestDist = nil, E.interactRadius for i, f in ipairs(E.floors) do local d = #(pc - vec3(f.coords.x, f.coords.y, f.coords.z)) if d <= bestDist then best, bestDist = i, d end end return best end local function teleport(idx) local f = E.floors[idx] if not f then return end local ped = PlayerPedId() DoScreenFadeOut(400) while not IsScreenFadedOut() do Wait(10) end RequestCollisionAtCoord(f.coords.x, f.coords.y, f.coords.z) SetEntityCoords(ped, f.coords.x, f.coords.y, f.coords.z, false, false, false, false) SetEntityHeading(ped, f.coords.w or 0.0) local id = GetInteriorAtCoords(f.coords.x, f.coords.y, f.coords.z) if id ~= 0 and IsValidInterior(id) then RefreshInterior(id) end local deadline = GetGameTimer() + 3000 while GetGameTimer() < deadline do local interiorReady = (id == 0) or IsInteriorReady(id) if HasCollisionLoadedAroundEntity(ped) and interiorReady then break end Wait(50) end DoScreenFadeIn(400) end RegisterNUICallback('go', function(data, cb) cb({}) closeMenu() local idx = tonumber(data.floor) if idx then teleport(idx) end end) RegisterNUICallback('close', function(_, cb) cb({}) closeMenu() end) local promptRunning = false local function promptLoop() if promptRunning then return end promptRunning = true while Standalone.isActive() do local near = nearestFloor() if near and shaftInteriorLoaded() then if not menuOpen then BeginTextCommandDisplayHelp('STRING') AddTextComponentSubstringPlayerName(E.helpText) EndTextCommandDisplayHelp(0, false, true, -1) if IsControlJustReleased(0, 38) then openMenu(near) end end Wait(0) else Wait(500) end end closeMenu() -- disarmed (scripts took over) — never leave focus stuck promptRunning = false end Standalone.onArm(promptLoop)