# Introduction Source: https://docs.nonefivem.com/cloud/api-reference/index Complete REST API reference for NoCloud The NoCloud API provides a RESTful interface for managing your cloud resources. All endpoints are designed to be simple, predictable, and consistent. ## Base URL All API requests should be made to: ``` https://api.nonefivem.com/cloud ``` ## Authentication All API requests require authentication using a Bearer token in the `Authorization` header. Your API key in the format: `Bearer ` ```bash theme={null} curl -X GET "https://api.nonefivem.com/cloud/storage" \ -H "Authorization: Bearer your-api-key" ``` Keep your API key secure. Do not expose it in client-side code or public repositories. ## Response Format All responses are returned in JSON format. Successful responses include the requested data, while error responses follow a consistent structure: ```json theme={null} { "message": "Error message describing what went wrong" } ``` ## HTTP Status Codes | Status Code | Description | | ----------- | ----------------------------------------- | | `200` | Success | | `201` | Created | | `400` | Bad Request - Invalid parameters | | `401` | Unauthorized - Invalid or missing API key | | `403` | Forbidden - Insufficient permissions | | `404` | Not Found - Resource doesn't exist | | `429` | Too Many Requests - Rate limit exceeded | | `500` | Internal Server Error | ## Permissions Different endpoints require different permission levels: | Permission | Description | | --------------- | ---------------------------------------- | | `STORAGE_READ` | Read storage items and statistics | | `STORAGE_WRITE` | Upload, delete, and modify storage items | ## Available Endpoints Get storage usage and statistics List and manage storage items Generate pre-signed upload URLs Configure retention policies # Bulk Delete Items Source: https://docs.nonefivem.com/cloud/api-reference/storage/bulk-delete DELETE /storage/bulk Delete multiple storage items in a single request Delete multiple storage items at once by providing an array of file IDs. This is more efficient than making individual delete requests. ## Authorization Bearer token for authentication. Format: `Bearer ` ## Required Permission `STORAGE_WRITE` ## Request Body Array of file UUIDs to delete. Minimum 1 ID, maximum 100 IDs per request. ## Response Success message indicating the operation result Number of items successfully deleted ```bash cURL theme={null} curl -X DELETE "https://api.nonefivem.com/cloud/storage/bulk" \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ "ids": [ "550e8400-e29b-41d4-a716-446655440000", "550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002" ] }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.nonefivem.com/cloud/storage/bulk", { method: "DELETE", headers: { Authorization: "Bearer your-api-key", "Content-Type": "application/json" }, body: JSON.stringify({ ids: [ "550e8400-e29b-41d4-a716-446655440000", "550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002" ] }) }); const result = await response.json(); ``` ```json Response theme={null} { "message": "3 items deleted successfully", "deletedCount": 3 } ``` This action is irreversible. Deleted files cannot be recovered. # Delete Storage Item Source: https://docs.nonefivem.com/cloud/api-reference/storage/delete-item DELETE /storage/{fileId} Delete a single storage item by ID Delete a specific storage item using its unique identifier. ## Authorization Bearer token for authentication. Format: `Bearer ` ## Required Permission `STORAGE_WRITE` ## Path Parameters UUID of the file to delete ## Response Success message confirming deletion ```bash cURL theme={null} curl -X DELETE "https://api.nonefivem.com/cloud/storage/550e8400-e29b-41d4-a716-446655440000" \ -H "Authorization: Bearer your-api-key" ``` ```javascript JavaScript theme={null} const fileId = "550e8400-e29b-41d4-a716-446655440000"; const response = await fetch( `https://api.nonefivem.com/cloud/storage/${fileId}`, { method: "DELETE", headers: { Authorization: "Bearer your-api-key" } } ); const result = await response.json(); ``` ```json Response theme={null} { "message": "Item deleted successfully" } ``` This action is irreversible. The file and its CDN URL will be permanently removed. ## Error Responses ```json 404 Not Found theme={null} { "error": { "code": "NOT_FOUND", "message": "Storage item not found" } } ``` ```json 400 Bad Request theme={null} { "error": { "code": "INVALID_UUID", "message": "Invalid file ID format" } } ``` # List Storage Items Source: https://docs.nonefivem.com/cloud/api-reference/storage/items GET /storage/items List storage items with pagination and filtering Retrieve a paginated list of storage items with optional filtering and sorting capabilities. ## Authorization Bearer token for authentication. Format: `Bearer ` ## Required Permission `STORAGE_READ` ## Query Parameters Page number (1-indexed) Number of items per page (1-100) Filter by file kind. Available values: `image`, `video`, `audio`, `document` ## Response Array of storage items Unique identifier (UUID) File kind: `image`, `video`, `audio`, or `document` File size in bytes Upload state: `pending` or `complete` Optional metadata attached to the file ISO 8601 timestamp of creation Total number of items Current page number Items per page Total number of pages ```bash cURL theme={null} curl -X GET "https://api.nonefivem.com/cloud/storage/items?page=1&limit=10&kind=image" \ -H "Authorization: Bearer your-api-key" ``` ```javascript JavaScript theme={null} const response = await fetch( "https://api.nonefivem.com/cloud/storage/items?page=1&limit=10&kind=image", { headers: { Authorization: "Bearer your-api-key" } } ); const result = await response.json(); ``` ```json Response theme={null} { "items": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "kind": "image", "size": 1048576, "state": "complete", "metadata": { "userId": "123" }, "createdAt": "2026-02-01T12:00:00Z" } ], "total": 150, "page": 1, "limit": 10, "totalPages": 15 } ``` # Purge Storage Items Source: https://docs.nonefivem.com/cloud/api-reference/storage/purge DELETE /storage/purge Purge storage items based on specified criteria Purge multiple storage items based on filtering criteria such as age, MIME type, or metadata. Use this for bulk cleanup operations. ## Authorization Bearer token for authentication. Format: `Bearer ` ## Required Permission `STORAGE_WRITE` ## Request Body Filter by file kind. Available values: `image`, `video`, `audio`, `document` ISO 8601 date - purge items created before this date ISO 8601 date - purge items created after this date ## Response Success message indicating the operation result Number of items purged (or would be purged if dry run) ```bash cURL theme={null} curl -X DELETE "https://api.nonefivem.com/cloud/storage/purge" \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ "kind": "image", "before": "2025-01-01T00:00:00Z" }' ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.nonefivem.com/cloud/storage/purge", { method: "DELETE", headers: { Authorization: "Bearer your-api-key", "Content-Type": "application/json" }, body: JSON.stringify({ kind: "image", before: "2025-01-01T00:00:00Z" }) }); const result = await response.json(); ``` ```json Response theme={null} { "message": "42 items purged successfully", "purgedCount": 42 } ``` This action is irreversible. Deleted files cannot be recovered. Combine `kind`, `before`, and `after` to target specific files. For example, purge all images created before a specific date. # Generate Signed URL Source: https://docs.nonefivem.com/cloud/api-reference/storage/signed-url GET /storage/signed-url Generate a pre-signed URL for direct file uploads Generate a pre-signed URL that allows direct file uploads to NoCloud storage. This is useful for client-side uploads where you don't want to proxy files through your server. ## Authorization Bearer token for authentication. Format: `Bearer ` ## Required Permission `STORAGE_WRITE` ## Query Parameters Query parameters are **optional**. Provide them only if you want to pre-allocate storage for the file. If omitted, a non-allocated signed URL is generated instead. MIME type of the file to upload Size of the file in bytes Optional metadata to attach to the file ## Response ### Without query parameters (non-allocated) The pre-signed URL for uploading. Upload to this URL using a **POST** request with the file as form data. You can optionally include a `metadata` field in the form data. ISO 8601 timestamp when the URL expires ### With query parameters (pre-allocated) When query parameters are provided, the response includes additional fields for the pre-allocated media: The pre-signed URL for uploading. Upload to this URL using a **PUT** request. ISO 8601 timestamp when the URL expires The ID the file will have after upload The public CDN URL where the file will be accessible after upload ```bash cURL (non-allocated) theme={null} curl -X GET "https://api.nonefivem.com/cloud/storage/signed-url" \ -H "Authorization: Bearer your-api-key" ``` ```bash cURL (pre-allocated) theme={null} curl -X GET "https://api.nonefivem.com/cloud/storage/signed-url?contentType=image/png&size=1048576" \ -H "Authorization: Bearer your-api-key" ``` ```javascript JavaScript (non-allocated) theme={null} const response = await fetch( "https://api.nonefivem.com/cloud/storage/signed-url", { headers: { Authorization: "Bearer your-api-key" } } ); const { url, expiresAt } = await response.json(); // Upload using POST with form data const formData = new FormData(); formData.append("file", fileBuffer); // Optionally attach metadata formData.append("metadata", JSON.stringify({ category: "screenshots" })); await fetch(url, { method: "POST", body: formData }); ``` ```javascript JavaScript (pre-allocated) theme={null} const params = new URLSearchParams({ contentType: "image/png", size: "1048576" }); const response = await fetch( `https://api.nonefivem.com/cloud/storage/signed-url?${params}`, { headers: { Authorization: "Bearer your-api-key" } } ); const { url, mediaId, mediaUrl } = await response.json(); // Upload directly to the signed URL using PUT await fetch(url, { method: "PUT", body: fileBuffer, headers: { "Content-Type": "image/png" } }); ``` ```json Non-allocated Response theme={null} { "url": "https://storage.nocloud.dev/upload/signed/abc123...", "expiresAt": "2026-02-06T13:00:00Z" } ``` ```json Pre-allocated Response theme={null} { "url": "https://storage.nocloud.dev/upload/signed/abc123...", "expiresAt": "2026-02-06T13:00:00Z", "mediaId": "550e8400-e29b-41d4-a716-446655440000", "mediaUrl": "https://cdn.nonefivem.com/c/{ORGANIZATION_ID}/550e8400-e29b-41d4-a716-446655440000" } ``` Signed URLs expire after 15 minutes. Generate a new URL if the upload doesn't complete in time. Learn how to upload files using signed URLs with complete examples in multiple languages. # Get Storage Statistics Source: https://docs.nonefivem.com/cloud/api-reference/storage/statistics GET /storage Retrieve storage usage statistics for your organization Returns comprehensive statistics about your organization's storage usage including total size, file counts, and usage breakdowns. ## Authorization Bearer token for authentication. Format: `Bearer ` ## Required Permission `STORAGE_READ` ## Response Total storage allocation in bytes Currently used storage in bytes Overage storage in bytes (usage beyond allocation) Breakdown of storage by file kind File kind: `image`, `video`, `audio`, or `document` Number of files of this kind Total size in bytes for this kind ```bash cURL theme={null} curl -X GET "https://api.nonefivem.com/cloud/storage" \ -H "Authorization: Bearer your-api-key" ``` ```javascript JavaScript theme={null} const response = await fetch("https://api.nonefivem.com/cloud/storage", { headers: { Authorization: "Bearer your-api-key" } }); const statistics = await response.json(); ``` ```json Response theme={null} { "totalStorage": 5368709120, "usedStorage": 1073741824, "overageStorage": 0, "breakdown": [ { "kind": "image", "count": 120, "size": 536870912 }, { "kind": "video", "count": 25, "size": 429496729 }, { "kind": "audio", "count": 5, "size": 107374183 } ] } ``` # Uploading Files Source: https://docs.nonefivem.com/cloud/api-reference/storage/uploading-files Learn how to upload files to NoCloud Storage NoCloud uses a two-step upload process: 1. **Get a signed URL** from the [Generate Signed URL](/cloud/api-reference/storage/signed-url) endpoint 2. **Upload the file** directly to the signed URL There are two modes depending on whether you provide query parameters: * **Non-allocated**: No query parameters — returns a signed URL. Upload with a **POST** request using form data. * **Pre-allocated**: Pass `contentType` and `size` as query parameters to pre-allocate storage — returns a signed URL along with `mediaId` and `mediaUrl`. Upload with a **PUT** request. This approach allows for efficient, direct-to-storage uploads without proxying through your backend. ## Simple Upload (Non-allocated) ```bash cURL theme={null} # Step 1: Get signed URL SIGNED_URL_RESPONSE=$(curl -s -X GET \ "https://api.nonefivem.com/cloud/storage/signed-url" \ -H "Authorization: Bearer your-api-key") # Extract the signed URL UPLOAD_URL=$(echo $SIGNED_URL_RESPONSE | jq -r '.url') # Step 2: Upload file via POST with form data curl -X POST "$UPLOAD_URL" \ -F "file=@./screenshot.png" \ -F 'metadata={"category":"screenshots"}' ``` ```javascript JavaScript theme={null} async function uploadFile(file) { // Step 1: Get signed URL const signedUrlResponse = await fetch( "https://api.nonefivem.com/cloud/storage/signed-url", { headers: { Authorization: "Bearer your-api-key" } } ); if (!signedUrlResponse.ok) { throw new Error("Failed to get signed URL"); } const { url } = await signedUrlResponse.json(); // Step 2: Upload file via POST with form data const formData = new FormData(); formData.append("file", file); // Optionally attach metadata formData.append("metadata", JSON.stringify({ category: "screenshots" })); const uploadResponse = await fetch(url, { method: "POST", body: formData }); if (!uploadResponse.ok) { throw new Error("Failed to upload file"); } return await uploadResponse.json(); } // Usage const file = document.querySelector('input[type="file"]').files[0]; const result = await uploadFile(file); console.log("File uploaded:", result); ``` ```typescript TypeScript theme={null} async function uploadFile(file: File | Blob): Promise { // Step 1: Get signed URL const signedUrlResponse = await fetch( "https://api.nonefivem.com/cloud/storage/signed-url", { headers: { Authorization: "Bearer your-api-key" } } ); if (!signedUrlResponse.ok) { throw new Error("Failed to get signed URL"); } const { url } = await signedUrlResponse.json(); // Step 2: Upload file via POST with form data const formData = new FormData(); formData.append("file", file); // Optionally attach metadata formData.append("metadata", JSON.stringify({ category: "screenshots" })); const uploadResponse = await fetch(url, { method: "POST", body: formData }); if (!uploadResponse.ok) { throw new Error("Failed to upload file"); } return await uploadResponse.json(); } ``` ## Pre-allocated Upload Pass `contentType` and `size` to pre-allocate storage. The response includes `mediaId` and `mediaUrl` so you know the file's location before uploading. ```bash cURL theme={null} # Step 1: Get signed URL with pre-allocation SIGNED_URL_RESPONSE=$(curl -s -X GET \ "https://api.nonefivem.com/cloud/storage/signed-url?contentType=image/png&size=1048576" \ -H "Authorization: Bearer your-api-key") # Extract the signed URL UPLOAD_URL=$(echo $SIGNED_URL_RESPONSE | jq -r '.url') # Step 2: Upload file to signed URL via PUT curl -X PUT "$UPLOAD_URL" \ -H "Content-Type: image/png" \ --data-binary @./screenshot.png ``` ```javascript JavaScript theme={null} async function uploadFile(file) { // Step 1: Get signed URL with pre-allocation const params = new URLSearchParams({ contentType: file.type, size: file.size.toString() }); const signedUrlResponse = await fetch( `https://api.nonefivem.com/cloud/storage/signed-url?${params}`, { headers: { Authorization: "Bearer your-api-key" } } ); if (!signedUrlResponse.ok) { throw new Error("Failed to get signed URL"); } const { url, mediaId, mediaUrl } = await signedUrlResponse.json(); // Step 2: Upload file directly to signed URL via PUT const uploadResponse = await fetch(url, { method: "PUT", body: file }); if (!uploadResponse.ok) { throw new Error("Failed to upload file"); } // Return the file info return { id: mediaId, url: mediaUrl }; } // Usage const file = document.querySelector('input[type="file"]').files[0]; const { id, url } = await uploadFile(file); console.log("File uploaded:", url); ``` ```typescript TypeScript theme={null} interface SignedUrlResponse { url: string; expiresAt: string; mediaId: string; mediaUrl: string; } interface UploadResult { id: string; url: string; } async function uploadFile(file: File | Blob): Promise { // Step 1: Get signed URL with pre-allocation const params = new URLSearchParams({ contentType: file.type, size: file.size.toString() }); const signedUrlResponse = await fetch( `https://api.nonefivem.com/cloud/storage/signed-url?${params}`, { headers: { Authorization: "Bearer your-api-key" } } ); if (!signedUrlResponse.ok) { throw new Error("Failed to get signed URL"); } const { url, mediaId, mediaUrl }: SignedUrlResponse = await signedUrlResponse.json(); // Step 2: Upload file directly to signed URL via PUT const uploadResponse = await fetch(url, { method: "PUT", body: file }); if (!uploadResponse.ok) { throw new Error("Failed to upload file"); } return { id: mediaId, url: mediaUrl }; } ``` ## Upload with Metadata (Pre-allocated) When using the pre-allocated flow, you can attach metadata via query parameters: ```javascript theme={null} const params = new URLSearchParams({ contentType: "image/png", size: file.size.toString(), // Metadata as JSON string metadata: JSON.stringify({ oderId: "order_123", visitorId: 456, isPublic: true }) }); const response = await fetch( `https://api.nonefivem.com/cloud/storage/signed-url?${params}`, { headers: { Authorization: "Bearer your-api-key" } } ); ``` Metadata constraints: - Maximum 10 keys - Key names: alphanumeric, underscores, hyphens only (max 128 chars) - Values: string (max 512 chars), number, or boolean - Total metadata size: max 2KB ## Upload with Progress Tracking For larger files, you may want to track upload progress. This example uses the pre-allocated flow: ```javascript theme={null} async function uploadWithProgress(file, onProgress) { // Get signed URL with pre-allocation const { url, mediaId, mediaUrl } = await getSignedUrl(file); return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", (event) => { if (event.lengthComputable) { const percentComplete = (event.loaded / event.total) * 100; onProgress(percentComplete); } }); xhr.addEventListener("load", () => { if (xhr.status >= 200 && xhr.status < 300) { resolve({ mediaId, mediaUrl }); } else { reject(new Error(`Upload failed with status ${xhr.status}`)); } }); xhr.addEventListener("error", () => reject(new Error("Upload failed"))); xhr.open("PUT", url); xhr.setRequestHeader("Content-Type", file.type); xhr.send(file); }); } // Usage await uploadWithProgress(file, (progress) => { console.log(`Upload progress: ${progress.toFixed(1)}%`); }); ``` Signed URLs expire after 15 minutes. Generate a new URL if the upload doesn't complete in time. # Introduction Source: https://docs.nonefivem.com/cloud/index NoCloud is an edge-powered cloud platform built for speed. Lightning-fast cloud services for game developers with ultra-low latency and global performance. ## What We Offer Secure and scalable storage solutions for your game data, player profiles, and assets. Native SDKs integrated for popular gaming platforms including FiveM, RedM, and Node.js applications. Comprehensive API documentation for seamless integration with your existing systems. Keep your game data synchronized across servers and clients in real-time. ## Why Choose NoCloud? * **Edge-Powered Performance** — Our infrastructure runs on the edge, delivering ultra-low latency responses globally. Speed isn't just a feature — it's our foundation. * **Built for Gaming** — Our platform is purpose-built for game developers, with features tailored to the unique demands of multiplayer gaming environments. * **Blazing Fast** — Every millisecond counts in gaming. Our edge network ensures your API calls are lightning-fast, no matter where your players are located. * **Powerful SDKs** — Integrate seamlessly with our native SDKs for CFX (FiveM/RedM) and Node.js, designed to get you up and running in minutes. * **Scalable Storage** — From small community servers to large-scale deployments, our storage and CDN scale with your needs. * **Developer-First** — Clean APIs, comprehensive documentation, and intuitive tools make development a breeze. * **Secure by Default** — Enterprise-grade security to protect your data and your players. ## Getting Started Ready to supercharge your game's storage and delivery? Explore our SDKs and start integrating today: For FiveM and RedM developers For server-side applications # Introduction Source: https://docs.nonefivem.com/cloud/integrations/index Integrate NoCloud storage with popular FiveM resources. ## Overview NoCloud can be integrated with third-party FiveM resources to handle media uploads such as images, videos, and audio files. These guides walk you through the setup process for each supported resource. Use NoCloud as the upload backend for lb-phone media. Use NoCloud for tgiann-core screenshot uploads. Use NoCloud as the upload backend for MPhone media. # LB Phone Source: https://docs.nonefivem.com/cloud/integrations/lb-phone Integrate NoCloud storage with lb-phone for media uploads. ## Overview This guide walks you through integrating NoCloud storage with **lb-phone** so that all image, video, and audio uploads go through NoCloud's API. There are **5 steps** to complete the integration: 1. Change the upload method to `Custom` 2. Whitelist the NoCloud domain 3. Set your NoCloud API keys 4. Add the `GetPresignedUrl` server function 5. Update the `UploadMethods` table *** ## Step 1: Change Upload Method Edit `lb-phone/config.lua` and find the `Config.UploadMethod` section. Change **all** values to `"Custom"`: ```lua theme={null} Config.UploadMethod.Video = "Custom" -- was "Fivemanage" Config.UploadMethod.Image = "Custom" -- was "Fivemanage" Config.UploadMethod.Audio = "Custom" -- was "Fivemanage" ``` This tells lb-phone to use the custom upload method defined in `shared/upload.lua`. *** ## Step 2: Whitelist NoCloud Domain In the same `lb-phone/config.lua` file, find `Config.UploadWhitelistedDomains` and add `"nonefivem.com"` to the list: ```lua theme={null} Config.UploadWhitelistedDomains = { "fivemanage.com", "fmfile.com", "cfx.re", "nonefivem.com" -- ADD THIS LINE } ``` This allows NoCloud URLs to be displayed inside the phone UI. *** ## Step 3: Set Your NoCloud API Keys Open `lb-phone/server/apiKeys.lua` and replace the API keys with your NoCloud API keys: ```lua theme={null} API_KEYS = { Video = "API_KEY_HERE", Image = "API_KEY_HERE", Audio = "API_KEY_HERE", } ``` Replace each `"API_KEY_HERE"` with your actual NoCloud API key. You can find your API key in the [NoCloud Dashboard](https://dash.nonefivem.com). *** ## Step 4: Add the `GetPresignedUrl` Function Open `lb-phone/server/custom/functions/functions.lua` and replace the following function. It fetches a signed upload URL from the NoCloud API: ```lua theme={null} ---@param source number ---@param uploadType "Audio" | "Image" | "Video" ---@return string? presignedUrl function GetPresignedUrl(source, uploadType) local apiKey = API_KEYS[uploadType] assert(type(apiKey) == "string", "API key for upload type '" .. uploadType .. "' is not defined in API_KEYS.") local p = promise.new() PerformHttpRequest("https://api.nonefivem.com/cloud/storage/signed-url", function(status, responseText, responseHeaders) if status == 200 then local data = json.decode(responseText) p:resolve(data.url) else print("Failed to get presigned URL. Response code: " .. status) p:resolve(nil) end end, "GET", { Authorization = string.format("Bearer %s", apiKey) }) local url = Citizen.Await(p) assert(type(url) == "string", "Failed to retrieve a valid presigned URL.") return url end ``` *** ## Step 5: Update `UploadMethods` Open `lb-phone/shared/upload.lua` and **replace** the existing `UploadMethods` table with the one below. The `Custom` entry is configured to work with NoCloud's presigned URLs: ```lua theme={null} ---@class UploadMethod ---@field url string # The url to upload to. Can use BASE_URL & PRESIGNED_URL as well. ---@field field string # The field name (formData) ---@field headers? table ---@field error? { path: string, value: any } # The path to the error value and the value to check for ---@field success { path: string } # The path to the video file ---@field suffix? string # Add a suffix to the url? Needed if the url doesn't return the correct file name ---@field sendPlayer? string # The formData field name to send player's metadata to, as json ---@field sendResource? boolean # Send the resource name in the formData? ---@type table UploadMethods = { Custom = { Default = { url = "PRESIGNED_URL", field = "file", success = { path = "url" }, sendPlayer = "metadata" }, }, Fivemanage = { Default = { url = "PRESIGNED_URL", field = "file", success = { path = "data.url" }, sendPlayer = "metadata" }, }, LBUpload = { Default = { url = "https://BASE_URL/lb-upload/", field = "file", headers = { ["Authorization"] = "API_KEY" }, error = { path = "success", value = false }, success = { path = "link" }, sendPlayer = "metadata" }, }, OldFivemanage = { Video = { url = "https://fmapi.net/api/v2/video", field = "file", headers = { ["Authorization"] = "API_KEY" }, success = { path = "data.url" }, }, Image = { url = "https://fmapi.net/api/v2/image", field = "file", headers = { ["Authorization"] = "API_KEY" }, success = { path = "data.url" } }, Audio = { url = "https://fmapi.net/api/v2/audio", field = "file", headers = { ["Authorization"] = "API_KEY" }, success = { path = "data.url" } }, }, } ``` *** ## Done After completing all 5 steps, restart your server. All media uploads from lb-phone (photos, videos, and audio) will now go through NoCloud storage. # mPhone Source: https://docs.nonefivem.com/cloud/integrations/mphone Integrate NoCloud storage with mPhone for media uploads. ## Overview This guide walks you through integrating NoCloud storage with **mPhone** so that all image, video, and audio uploads go through NoCloud's API. There are **2 steps** to complete the integration: 1. Change the `activeProvider` to `NoCloud` 2. Update your NoCloud API key *** ## Step 1: Change the Active Provider Open your mPhone upload configuration and find the `UploadService` section. Change `activeProvider` to `'NoCloud'`: ```lua theme={null} UploadService = { activeProvider = 'NoCloud', -- Change this to 'NoCloud' -- NoCloud signed URL endpoint nocloudEndpoint = 'https://api.nonefivem.com/cloud/storage/signed-url', -- API credentials by media type apiKeys = { audio = '', video = '', image = '', nocloud = '' -- NoCloud API key (get from https://dash.nonefivem.com) } } ``` *** ## Step 2: Set Your NoCloud API Key In the `apiKeys` table, set the `nocloud` key to your NoCloud API key. You can find your API key in the [NoCloud Dashboard](https://dash.nonefivem.com). ```lua theme={null} apiKeys = { nocloud = 'YOUR_NOCLOUD_API_KEY' -- Replace with your actual NoCloud API key } ``` You only need to set the `nocloud` key. The `audio`, `video`, and `image` keys are used by other providers like Fivemanage and can be left empty. *** ## Done After completing both steps, restart your server. All media uploads from mPhone (photos, videos, and audio) will now go through NoCloud storage. # tgiann Source: https://docs.nonefivem.com/cloud/integrations/tgiann Integrate NoCloud storage with tgiann-core for screenshot uploads. ## Overview This guide walks you through integrating NoCloud storage with **tgiann-core** so that screenshot uploads are handled through the NoCloud CFX SDK. There are **2 steps** to complete the integration: 1. Install the NoCloud CFX SDK on your server 2. Update the tgiann-core screenshot config *** ## Step 1: Install the NoCloud CFX SDK You need the **NoCloud CFX SDK** (`nocloud`) installed and running on your server. Follow the installation guide to get it set up: Step-by-step instructions to install and configure the NoCloud CFX SDK. *** ## Step 2: Update the Screenshot Config Open `tgiann-core/configs/screenshotConfig.lua` and set `nonefivem.active` to `true`: ```lua theme={null} configCore.screenshot = { fivemanage = { active = false, api = '', }, nonefivem = { active = true, -- Set to true to enable nonefivem screenshot upload scriptName = 'nocloud', -- nocloud script name, change if you renamed the resource }, discordWebhook = "" } ``` If you renamed the `nocloud` resource, update the `scriptName` value to match your resource name. Make sure `fivemanage.active` is set to `false`. If fivemanage is active, the nonefivem configuration will be ignored. # Storage & CDN Source: https://docs.nonefivem.com/cloud/offers/storage NoCloud Storage provides a powerful and globally distributed public file storage solution designed specifically for game developers. Combined with our integrated CDN, your content is always fast, reliable, and accessible worldwide. ## Overview Our storage platform is built for serving public content with maximum performance: Upload and serve public files like images, screenshots, and game assets with simple API calls. Deliver content lightning-fast with our worldwide content delivery network, ensuring low latency for players everywhere. NoCloud Storage is designed for **public files only**. All uploaded files are publicly accessible via CDN URLs. Do not upload sensitive or private data. ## Key Features ### Public File Hosting * **Instant Availability** — Files are immediately available via CDN after upload. * **Permanent URLs** — Each file receives a unique, permanent URL that never changes. * **Multiple Formats** — Support for images, audio, and other common file types. ### High-Performance CDN * **Global Edge Network** — Content is cached at edge locations worldwide, reducing latency for players in any region. * **Smart Caching** — Intelligent cache management ensures players always receive content quickly. * **Unlimited Bandwidth** — No bandwidth fees — you only pay for storage, not delivery. ### Developer-Friendly * **Simple API** — RESTful API endpoints make uploading and retrieving files straightforward. * **SDK Support** — Native SDKs for CFX (FiveM/RedM) and Node.js handle uploads and URL generation for you. * **Direct URLs** — Get direct CDN URLs for immediate use in your game or application. ## Use Cases Let players capture and share in-game screenshots. Perfect for polaroid scripts, galleries, and social features. Host custom images, logos, and visual assets that need to be accessible from your game client. Allow players to upload and share content like crew logos, custom images, and more. Store and serve media files that need to be accessible across multiple servers or applications. ## How It Works ```mermaid theme={null} sequenceDiagram participant Game as Your Game participant API as NoCloud API participant CDN as Global CDN Game->>API: Upload file API->>CDN: Distribute to edge API-->>Game: Return CDN URL Game->>CDN: Request file CDN-->>Game: Serve cached file ``` 1. **Upload** — Send your file to NoCloud via API or SDK 2. **Distribute** — Your file is stored and distributed across our global CDN 3. **Receive URL** — Get a permanent CDN URL for your file 4. **Serve** — Use the URL anywhere — files are served from the nearest edge location ## Getting Started Ready to integrate NoCloud Storage into your project? Check out our SDK documentation: Storage integration for FiveM and RedM Storage integration for Node.js applications ## Pricing **Start free, scale as you grow.** Get free storage to get started, then pay only for what you use as your needs expand — **bandwidth is always free**. No hidden fees for downloads or CDN delivery, no matter how many times your files are accessed. ### How Billing Works We take **daily snapshots** of your storage usage throughout the billing period. At the end of each billing cycle (1 month), you're charged based on the **average usage** across all those daily snapshots — not your peak usage. This means you're not penalized for temporary spikes. If you upload a large batch of files and delete them a few days later, you only pay for the days they were stored. ### Minimum Billable Object Size Every stored object has a **minimum billable size of 32 KB**. If a file is smaller than 32 KB, it will be calculated as 32 KB for billing purposes. This covers the infrastructure and processing overhead associated with storing and serving each individual object. **Example 1: Steady Growth** * Week 1-2: 10 GB stored * Week 3-4: 30 GB stored Average usage: $(10 \times 14 + 30 \times 14) \div 28 = 20$ GB You'd be billed for **20 GB**, not the peak of 30 GB. *** **Example 2: Temporary Spike** * Days 1-25: 5 GB stored * Days 26-28: 50 GB stored (big upload) * Days 29-30: 5 GB stored (cleanup) Average usage: $(5 \times 25 + 50 \times 3 + 5 \times 2) \div 30 \approx 9.5$ GB You'd be billed for roughly **9.5 GB**, not the peak of 50 GB. *** **Example 3: Constant Usage** * All 30 days: 15 GB stored Average usage: **15 GB** Simple and predictable! See our [dashboard](https://dash.nonefivem.com) for current usage and plan details. Need higher storage limits or enterprise features? [Contact us](mailto:support@nonefivem.com) for custom plans. # Configuration Source: https://docs.nonefivem.com/cloud/sdks/cfx/configuration Configure the NoCloud CFX SDK for security, rate limiting, and storage options The SDK is configured via the `config.json` file located in the root of your `nocloud` resource folder. The default configuration is preconfigured with secure defaults and sensible limits—you can adjust these values to fit your needs. The `$schema` property enables autocomplete and validation in editors like VS Code. *** ## Logging Enable or disable logging output. The minimum log level to output. | Level | Description | | ------- | ----------------------------- | | `debug` | Verbose debugging information | | `info` | General operational messages | | `warn` | Warning messages | | `error` | Error messages only | *** ## Storage Whether clients can trigger uploads from their game client or nui. Maximum allowed file size in megabytes. Files exceeding this limit will be rejected. An array of MIME types permitted for upload. Any file type not in this list will be rejected. | Category | MIME Types | | --------- | --------------------------------------------------------------------- | | Images | `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/svg+xml` | | Video | `video/mp4`, `video/webm` | | Audio | `audio/mpeg`, `audio/wav` | | Documents | `text/plain` | *** ## Rate Limiting Per-client rate limiting prevents abuse by restricting how many uploads each client can make within a time window. Enable or disable rate limiting. The time window in milliseconds for rate limit tracking. | Value | Duration | | --------- | --------- | | `60000` | 1 minute | | `300000` | 5 minutes | | `3600000` | 1 hour | Maximum number of upload requests allowed per client within the time window. Defines how clients are uniquely identified for rate limiting. This is a colon-separated list of identifiers. | Identifier | Description | | ---------- | --------------------------- | | `ip` | Client's IP address | | `license` | Rockstar license identifier | | `steam` | Steam ID (if available) | | `discord` | Discord ID (if available) | | `fivem` | FiveM account ID | **Examples:** * `ip:license` — Combines IP and license (default) * `license` — License only * `ip:license:steam` — Multiple identifiers # Introduction Source: https://docs.nonefivem.com/cloud/sdks/cfx/index NoCloud CFX SDK provides seamless integration with the NoCloud platform, enabling FiveM and RedM servers to capture in-game screenshots and upload them directly to cloud storage. ## Features Uses `@citizenfx/three` and `CfxTexture` for direct game view capture Upload screenshots directly to NoCloud's serverless storage Secure uploads with pre-signed URLs Self-contained, no external resources required Full type safety across client, server, and NUI ## Next Steps Learn how to install the SDK Browser-based integration # Installation Source: https://docs.nonefivem.com/cloud/sdks/cfx/installation How to install the NoCloud CFX SDK Download the latest release from [GitHub Releases](https://github.com/nonefivem/no-cloud-cfx/releases). Unzip the downloaded file and place the `nocloud` folder into your server's `resources` directory. ``` resources/ └── nocloud/ ``` Add the following line to your `server.cfg` to ensure the resource starts: ```cfg theme={null} ensure nocloud ``` Add your NoCloud API key to your `server.cfg`: ```cfg theme={null} set NOCLOUD_API_KEY "your_api_key" ``` You can get your API key from the [NoCloud Dashboard](https://dash.nonefivem.com). # Introduction Source: https://docs.nonefivem.com/cloud/sdks/cfx/nui/index NoCloud NUI SDK - TypeScript library for uploading files from NUI to NoCloud storage TypeScript client library for uploading files from CFX NUI (browser) to NoCloud storage. Seamless integration with the [CFX SDK](/cloud/cfx) - handles signed URLs and secure uploads automatically without exposing API keys. This SDK requires the [CFX SDK](/cloud/cfx/installation) to be running on your server. If the `nocloud` resource is not available, methods will throw a `NoCloudResourceIsNotFound` error. ## Features Works with CFX SDK out of the box API keys never exposed to the browser Lightweight, self-contained library Full type safety ## Next Steps Install the NUI SDK Upload files from NUI # Installation Source: https://docs.nonefivem.com/cloud/sdks/cfx/nui/installation How to install the NoCloud NUI SDK Choose your preferred installation method: Install the package using your preferred package manager: ```bash npm theme={null} npm install @nocloud/cfx-nui ``` ```bash bun theme={null} bun add @nocloud/cfx-nui ``` ```bash pnpm theme={null} pnpm add @nocloud/cfx-nui ``` ```bash yarn theme={null} yarn add @nocloud/cfx-nui ``` Add the SDK directly to your HTML using jsDelivr: ```html theme={null} ``` The `NoCloud` object will be available globally. If using a package manager, import the SDK in your code: ```typescript theme={null} import { NoCloud } from "@nocloud/cfx-nui"; ``` If using the CDN script tag, skip this step. The `NoCloud` object is available globally. # Storage Source: https://docs.nonefivem.com/cloud/sdks/cfx/nui/storage Upload files from NUI to NoCloud storage ## Methods Checks if the NoCloud service is available by pinging the service endpoint. ```typescript theme={null} const available = await NoCloud.isAvailable(); if (available) { console.log("NoCloud service is available"); } else { console.log("NoCloud service is not available"); } ``` **Returns** * `Promise` - `true` if the service is available Uploads a file to NoCloud storage. ```typescript theme={null} const fileInput = document.querySelector('input[type="file"]'); const file = fileInput.files[0]; const { id, url } = await NoCloud.storage.upload(file, { category: "user-uploads", userId: "12345" }); console.log("Media ID:", id); console.log("File uploaded to:", url); ``` **Parameters** * file: `Blob | File` - The file or blob to upload * metadata: `Record` - Key-value pairs for custom metadata (optional) **Returns** * id: `string` - Unique media ID * url: `string` - The media URL of the uploaded file Obtains a presigned URL for uploading a file. ```typescript theme={null} const { url, mediaUrl } = await NoCloud.storage.getPresignedUrl( "image/png", // Content type 1024000, // File size in bytes { category: "screenshots", userId: "12345" } ); // url: The presigned URL to upload the file // mediaUrl: The final URL where the file will be accessible ``` **Parameters** * contentType: `string` - MIME type of the file (e.g., `image/png`) * size: `number` - File size in bytes * metadata: `Record` - Key-value pairs for custom metadata (optional) **Returns** * url: `string` - The presigned URL to upload the file * mediaUrl: `string` - The final URL where the uploaded file will be accessible ## Examples ### Upload a File ```typescript theme={null} async function uploadFile(file: File) { try { const { id, url } = await NoCloud.storage.upload(file, { customMeta: "value", userId: "12345" }); console.log("Media ID:", id); console.log("File uploaded to:", url); } catch (error) { console.error("Upload failed:", error); } } ``` ### Upload Canvas Data ```typescript theme={null} // Upload any Blob (e.g., canvas data) const blob = await fetch(canvasDataUrl).then((r) => r.blob()); const { id, url } = await NoCloud.storage.upload(blob, { type: "canvas-export", timestamp: Date.now() }); ``` ## Error Handling All methods throw errors when operations fail. Always wrap calls in try-catch blocks: ```typescript theme={null} try { const media = await NoCloud.storage.upload(file); console.log("Success:", media.url); } catch (error) { console.error("Upload failed:", error); } ``` # Client Exports Source: https://docs.nonefivem.com/cloud/sdks/cfx/storage/client-exports Client-side exports for capturing and uploading screenshots ## Exports Captures a screenshot and uploads it to cloud storage. ```lua theme={null} local result = exports.nocloud:TakeImage({ category = 'screenshots', playerId = GetPlayerServerId(PlayerId()) }) if result then print('Screenshot uploaded:', result.url) print('Media ID:', result.id) end ``` **Parameters** * metadata: `table` - Key-value pairs for custom metadata (optional) **Returns** * url: `string` - Public URL of the uploaded image * id: `string` - Unique media ID for reference Generates a pre-signed URL for client-side uploads. ```lua theme={null} local signedUrl = exports.nocloud:GenerateSignedUrl('image/png', 1024, { category = 'screenshots', owner = 'player123' }) ``` **Parameters** * mimeType: `string` - MIME type of the file (e.g., `image/png`) * size: `number` - File size in bytes * metadata: `table` - Key-value pairs for custom metadata (optional) **Returns** * signedUrl: `string` - Pre-signed URL for uploading ## Lua Library For a cleaner API, include the client Lua library in your `fxmanifest.lua`: ```lua theme={null} client_script '@nocloud/lib/client.lua' ``` **Usage** ```lua theme={null} local result = Cloud.storage:take_image({ category = 'screenshots' }) if result then print('Uploaded:', result.url) end ``` # Introduction Source: https://docs.nonefivem.com/cloud/sdks/cfx/storage/index Cloud storage API for uploading and managing media files ## Overview The Storage API allows you to upload screenshots and files directly to NoCloud's serverless storage. It provides both client-side and server-side exports for flexible integration with additional lua libraries. Capture screenshots and upload from the client Upload files and manage media from the server # Server Exports Source: https://docs.nonefivem.com/cloud/sdks/cfx/storage/server-exports Server-side exports for uploading and managing media files ## Exports Generates a pre-signed URL for uploading files. ```lua theme={null} local signedUrl = exports.nocloud:GenerateSignedUrl('image/png', 1024, { category = 'screenshots', owner = 'player123' }) ``` **Parameters** * mimeType: `string` - MIME type of the file (e.g., `image/png`, `image/jpeg`) * size: `number` - File size in bytes * metadata: `table` - Key-value pairs for custom metadata (optional) **Returns** * signedUrl: `string` - Pre-signed URL for uploading Uploads a file directly using base64 or raw data. ```lua theme={null} local result = exports.nocloud:UploadMedia(base64Data, { category = 'documents', owner = 'player123' }) if result then print('File uploaded:', result.url) print('Media ID:', result.id) end ``` **Parameters** * data: `string` - Base64 encoded file data * metadata: `table` - Key-value pairs for custom metadata (optional) **Returns** * url: `string` - Public URL of the uploaded file * id: `string` - Unique media ID Deletes a file from cloud storage. ```lua theme={null} local success = exports.nocloud:DeleteMedia(mediaId) if success then print('File deleted successfully') end ``` **Parameters** * mediaId: `string` - The media ID to delete **Returns** * success: `boolean` - `true` if deletion was successful ## Lua Library For a cleaner API, include the server Lua library in your `fxmanifest.lua`: ```lua theme={null} server_script '@nocloud/lib/server.lua' ``` **Usage** ```lua theme={null} -- Generate signed URL local signedUrl = Cloud.storage:generate_signed_url('image/png', 1024) -- Upload file local result = Cloud.storage:upload(base64Data, { category = 'files' }) -- Delete file local success = Cloud.storage:delete_media(mediaId) ``` # Error Handling Source: https://docs.nonefivem.com/cloud/sdks/nodejs/error-handling Handle errors gracefully with NoCloudAPIError The SDK provides detailed error handling through `NoCloudAPIError` and the `NoCloudError` enum. ## Basic Error Handling ```typescript theme={null} import { NoCloud, NoCloudAPIError } from "@nocloud/sdk"; const cloud = new NoCloud("your-api-key"); try { await cloud.storage.upload(file); } catch (error) { if (error instanceof NoCloudAPIError) { console.error(`API Error: ${error.message}`); console.error(`Status: ${error.status}`); console.error(`Code: ${error.code}`); } } ``` ## Check for Specific Errors Use the static `isError` method to check for specific error types: ```typescript theme={null} import { NoCloudAPIError, NoCloudError } from "@nocloud/sdk"; try { await cloud.storage.upload(file); } catch (error) { if (NoCloudAPIError.isError(error, NoCloudError.RATE_LIMIT_EXCEEDED)) { console.log("Rate limited, retry later"); } else if (NoCloudAPIError.isError(error, NoCloudError.INVALID_API_KEY)) { console.log("Check your API key"); } else if (NoCloudAPIError.isError(error)) { console.log(`Other API error: ${error.code}`); } } ``` ## Error Codes | Code | HTTP Status | Description | | ----------------------- | ----------- | -------------------------- | | `INVALID_API_KEY` | 401 | Invalid or missing API key | | `BAD_REQUEST` | 400 | Invalid request parameters | | `RATE_LIMIT_EXCEEDED` | 429 | Too many requests | | `RESOURCE_NOT_FOUND` | 404 | File or resource not found | | `INTERNAL_SERVER_ERROR` | 500 | Server error | | `UNKNOWN_ERROR` | — | Unexpected error | ## NoCloudAPIError Properties | Property | Type | Description | | --------- | -------------- | ---------------------------- | | `message` | `string` | Human-readable error message | | `status` | `number` | HTTP status code | | `code` | `NoCloudError` | Error code enum value | ## Retry Logic The SDK includes built-in retry logic for transient failures. You can configure the retry behavior when initializing: ```typescript theme={null} const cloud = new NoCloud({ apiKey: "your-api-key", retries: 5, // Retry up to 5 times retryDelayMs: 2000 // Wait 2 seconds between retries }); ``` The SDK will automatically retry failed requests for transient errors (like network issues). It will not retry for client errors like invalid API keys or bad requests. ## Handling Rate Limits When you exceed the rate limit, the SDK throws a `RATE_LIMIT_EXCEEDED` error: ```typescript theme={null} import { NoCloudAPIError, NoCloudError } from "@nocloud/sdk"; async function uploadWithRetry(file: File, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await cloud.storage.upload(file); } catch (error) { if (NoCloudAPIError.isError(error, NoCloudError.RATE_LIMIT_EXCEEDED)) { // Wait before retrying await new Promise((resolve) => setTimeout(resolve, 5000)); continue; } throw error; } } throw new Error("Max retries exceeded"); } ``` # Introduction Source: https://docs.nonefivem.com/cloud/sdks/nodejs/index Official Node.js SDK for NoCloud services — upload and manage files with a simple, type-safe API. The `@nocloud/sdk` package provides a simple and type-safe way to interact with NoCloud services from any Node.js or browser environment. ## Features Intuitive methods for uploading and managing files Full type safety with comprehensive TypeScript definitions Supports File, Blob, ArrayBuffer, base64 strings, and streams Built-in retry logic for reliable uploads Works in Node.js (≥18) and browser environments Just add your API key and start uploading ## Next Steps Install the SDK and configure your project Upload and manage files Handle errors gracefully Explore the full API documentation Learn more about our storage platform # Installation Source: https://docs.nonefivem.com/cloud/sdks/nodejs/installation How to install the NoCloud Node.js SDK ## Package Installation Install the SDK using your preferred package manager: ```bash npm theme={null} npm install @nocloud/sdk ``` ```bash bun theme={null} bun add @nocloud/sdk ``` ```bash pnpm theme={null} pnpm add @nocloud/sdk ``` ```bash yarn theme={null} yarn add @nocloud/sdk ``` ## Quick Start ```typescript theme={null} import { NoCloud } from "@nocloud/sdk"; // Initialize with your API key const cloud = new NoCloud("your-api-key"); // Upload a file const file = new File(["Hello, NoCloud!"], "hello.txt", { type: "text/plain" }); const { id, url } = await cloud.storage.upload(file); console.log(`Uploaded: ${url}`); // Delete when done await cloud.storage.delete(id); ``` You can get your API key from the [NoCloud Dashboard](https://dash.nonefivem.com). ## Configuration Options You can pass an options object for more control: ```typescript theme={null} const cloud = new NoCloud({ apiKey: "your-api-key", baseUrl: "https://api.nonefivem.com", // optional, default API URL basePath: "/cloud", // optional, default base path retries: 3, // optional, retry attempts (default: 3) retryDelayMs: 1000 // optional, delay between retries (default: 1000ms) }); ``` | Option | Type | Default | Description | | -------------- | -------- | --------------------------- | -------------------------------------------- | | `apiKey` | `string` | — | **Required.** Your NoCloud API key | | `baseUrl` | `string` | `https://api.nonefivem.com` | API base URL | | `basePath` | `string` | `/cloud` | Base path for API endpoints | | `retries` | `number` | `3` | Number of retry attempts for failed requests | | `retryDelayMs` | `number` | `1000` | Delay in ms between retry attempts | ## Compatibility The SDK works in both Node.js and browser environments: * **Node.js**: Version 18 or higher (uses native `fetch`) * **Browser**: All modern browsers with `fetch` support No Node-specific APIs are used, making it fully compatible with edge runtimes and browser environments. # Storage Source: https://docs.nonefivem.com/cloud/sdks/nodejs/storage Upload and manage files with the NoCloud Storage API The Storage API allows you to upload files directly to NoCloud's serverless storage and manage them programmatically. ## Upload a File Upload files using various input types: ```typescript theme={null} // From File or Blob const file = new File(["content"], "file.txt", { type: "text/plain" }); const { id, url } = await cloud.storage.upload(file); // From ArrayBuffer const buffer = new TextEncoder().encode("Hello!").buffer; const { id, url } = await cloud.storage.upload(buffer); // From base64 string (auto-detects MIME type) const base64 = "data:image/png;base64,iVBORw0KGgo..."; const { id, url } = await cloud.storage.upload(base64); // With metadata const { id, url } = await cloud.storage.upload(file, { userId: "123", category: "avatars", isPublic: true }); ``` ### Response ```typescript theme={null} interface UploadResponse { id: string; // Unique identifier for the uploaded file url: string; // Public CDN URL to access the file } ``` ## Upload a Stream For large files, use streaming uploads: ```typescript theme={null} const stream = getReadableStream(); // Your ReadableStream const { id, url } = await cloud.storage.uploadStream( stream, "video/mp4", // Content type fileSize // Content length in bytes ); ``` ### Parameters | Parameter | Type | Description | | --------------- | ---------------- | ---------------------------- | | `stream` | `ReadableStream` | The stream to upload | | `contentType` | `string` | MIME type of the content | | `contentLength` | `number` | Size of the content in bytes | | `metadata` | `FileMetadata` | Optional metadata object | ## Generate Signed URL Get a pre-signed URL for direct uploads (useful for client-side uploads): ```typescript theme={null} const signedUrl = await cloud.storage.generateSignedUrl( "image/png", // Content type 1024, // File size in bytes { userId: "123" } // Optional metadata ); ``` ### Response ```typescript theme={null} interface SignedUrlResponse { url: string; // The signed URL for uploading expiresAt: string; // Expiration time (ISO 8601) mediaId: string; // The ID the file will have after upload mediaUrl: string; // The public URL after upload } ``` ### Using a Signed URL After getting a signed URL, you can upload directly: ```typescript theme={null} const { url, mediaId, mediaUrl } = await cloud.storage.generateSignedUrl( "image/png", fileSize ); // Upload directly to the signed URL await fetch(url, { method: "PUT", headers: { "Content-Length": fileSize.toString() }, body: fileData }); // File is now available at mediaUrl console.log(`Uploaded: ${mediaUrl}`); ``` ## Delete Files Delete a single file or multiple files: ```typescript theme={null} // Delete a single file await cloud.storage.delete(mediaId); // Delete multiple files (batched automatically, max 100 per batch) await cloud.storage.delete([mediaId1, mediaId2, mediaId3]); ``` When deleting multiple files, the SDK automatically batches requests in groups of 100 for optimal performance. ## Supported Body Types | Type | Description | | ------------- | -------------------- | | `File` | Browser File object | | `Blob` | Binary data | | `ArrayBuffer` | Raw binary buffer | | `string` | Base64 or plain text | Base64 strings with data URLs (`data:image/png;base64,...`) or raw base64 are automatically detected and the MIME type is inferred. ## Metadata You can attach custom metadata to your uploads: ```typescript theme={null} type FileMetadata = Record; // Example const { id, url } = await cloud.storage.upload(file, { userId: "user_123", uploadedAt: Date.now(), isAvatar: true }); ``` Metadata is stored with the file and can be used for organization and filtering. # Exports & Events Source: https://docs.nonefivem.com/scripts/no-alerts/exports-and-events ## Exports Sends notification. **Parameters** * notification: [Notification Data](/no-alerts/notification-usage#notification) | string * icon?: string * color?: string * timeout?: number Shows single indicator on screen. **Parameters** * indicator: [Indicator Data](/no-alerts/indicator-usage#indicator) Shows indicator group on screen **Parameters** * indicators: [Indicator Data](/no-alerts/indicator-usage#indicator)\[] Removes single indicator on screen Removes indicator group on screen ## Client Net Events Sends notification. **Parameters** * notification: [Notification Data](/no-alerts/notification-usage#notification) | string * icon?: string * color?: string * timeout?: number Shows single indicator on screen. **Parameters** * indicator: [Indicator Data](/no-alerts/indicator-usage#indicator) Shows indicator group on screen **Parameters** * indicators: [Indicator Data](/no-alerts/indicator-usage#indicator)\[] Removes single indicator on screen. Removes indicator group on screen # Introduction Source: https://docs.nonefivem.com/scripts/no-alerts/index FiveM resource for showing notification & indicators. [Tebex Page](https://store.nonefivem.com/packages/5872318). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-alerts` to your server cfg after no-base. # Indicator Usage Source: https://docs.nonefivem.com/scripts/no-alerts/indicator-usage ## Types ### Indicator | Field | Type | Description | Required | | ----- | ------------------- | ----------------- | -------- | | text | string | Text to show | ✓ | | keys | string \| string\[] | Key list to show | | | key | string | Key to show | | | icon | string | Font Awesome Icon | | *** ## Examples ```lua theme={null} exports["no-alerts"]:SetIndicator({ -- Shows single indicator text = "Enter", key = "E", icon = "door-open" }) exports["no-alerts"]:CloseIndicator() -- Hides single indicator ``` ```lua theme={null} exports["no-alerts"]:SetIndicators({ -- Shows indicator group { text = "Current Bet: 500", icon = "coins" }, { text = "Change Bet", -- You can pass icon as a key by adding icon:: before the icon's name keys = {"icon::arrow-left", "icon::arrow-right"}, icon = "money-bill-transfer" }, { text = "Leave", key = "F", icon = "door-open" } }) exports["no-alerts"]:CloseIndicators() -- Hides indicator group ``` # Notification Usage Source: https://docs.nonefivem.com/scripts/no-alerts/notification-usage ## Types ### Notification | Field | Type | Description | Required | | --------- | ------------------- | ----------------- | -------- | | text | string | Text to show | ✓ | | leftIcon | string \| string\[] | Font Awesome Icon | | | rightIcon | string | Font Awesome Icon | | | color | string | Color hex code | | | timeout | number | Remove timeout | | *** ## Examples ```lua theme={null} TriggerEvent("no-alerts:notification", { text = "You've entered the danger zone", leftIcon = "radiation" }) exports["no-alerts"]:SendNotification("You left the danger zone", "radiation", "#F92F04") ``` # Indicators Source: https://docs.nonefivem.com/scripts/no-base/configuration/indicators/index You can use our built-in UI for indicators, or configure it to match your server's setup.\ Most popular scripts are supported under the hood, so if you're using one of them, simply configure it in `no-base/configure/indicators` and set `useNative` to `false`. # Indicators Source: https://docs.nonefivem.com/scripts/no-base/configuration/indicators/indicator ## Default Indicators
default indicators

Indicators

default indicator

Indicator

You can override default behavior from `no-base/configure/client/alerts.lua` #### [Indicator Data](/no-alerts/indicator-usage#indicator) ```lua theme={null} Config.Alerts = { setIndicator = function(indicator) TriggerEvent("indicator:show", indicator) end, setIndicators = function(indicators) TriggerEvent("indicators:show", indicators) end, closeIndicator = function() TriggerEvent("indicator:hide") end, closeIndicators = function() TriggerEvent("indicators:hide") end } ``` # Notification Source: https://docs.nonefivem.com/scripts/no-base/configuration/indicators/notifications ## Default Notification
default notification

Notification

You can override default behavior from `no-base/configure/client/indicators.lua` #### Parameters * text: string * err?: boolean * icon?: string (Font awesome icon) * timeout?: number ```lua theme={null} Config.Indicators = { notification = function(text, err, icon, timeout) TriggerEvent("notification", text, err, icon, timeout) end } ``` # Interact (Target) Source: https://docs.nonefivem.com/scripts/no-base/configuration/interact-target If you're using [supported interact resource](/no-base/supported-resources#interact-target) you dont have to make any changes in this section. > You can override interact actions from `no-base/configure/client/interact.lua` ## Types *** ### Entry | Field | Type | Description | | ---------- | ------- | ----------------------------- | | id | string | Unique id for entry | | label | string | Label for entry | | icon | string? | Font awesome icon name | | event | string | Client event to trigger | | parameters | any? | Parameters to pass with event | ### Distance | Field | Type | Description | | ------ | ------- | ---------------------------------- | | radius | number? | Distance between entity and player | ### Options | Field | Type | Description | | --------- | ------------------------- | ---------------------------------------- | | distance | [Distance](#distance)? | Distance data | | isEnabled | function(entity: number)? | Function to check is entity interactable | ## Examples *** This is an example of how we handle qb-target. Since we support qb-target internally you don't need to make any changes if you use qb-target. Make sure to trigger the given event as in the example. ```lua theme={null} AddEventHandler("no-base:interact:qb", function(response) TriggerEvent(response.data.event, response.data.parameters, response.entity) end) Config.Interact = { AddEntryByModel = function(models, entries, options) local function canInteract(entity) return not options.isEnabled or options.isEnabled(entity) end local _entries = {} for _, entry in pairs(entries) do _entries[#_entries + 1] = { icon = "fas fa-" .. entry.icon, label = entry.label, event = "no-base:interact:qb", data = {event = entry.event, parameters = entry.parameters}, distance = options.distance?.radius, bones = options.bone and {options.bone} or options.bones, canInteract = canInteract } end local resource = GetInvokingResource() local handler handler = AddEventHandler("onResourceStop", function(resName) if resName ~= resource then return end RemoveEventHandler(handler) local labels = {} for _, entry in pairs(_entries) do labels[#labels + 1] = entry.label end exports["qb-target"]:RemoveTargetModel(models, labels) end) return exports["qb-target"]:AddTargetModel(models, { options = _entries, distance = options.distance?.radius }) end, AddEntryBySphereZone = function(coords, radius, entries, options) local zoneId = entries[1] and entries[1].id if not zoneId then return end local function canInteract(entity) return not options.isEnabled or options.isEnabled(entity) end local _entries = {} for _, entry in pairs(entries) do _entries[#_entries + 1] = { icon = "fas fa-" .. entry.icon, label = entry.label, event = "no-base:interact:qb", data = {event = entry.event, parameters = entry.parameters}, distance = options.distance?.radius, bones = options.bone and {options.bone} or options.bones, canInteract = canInteract } end exports["qb-target"]:AddCircleZone(zoneId, coords, radius, { name = zoneId, useZ = true }, { options = _entries, distance = options.distance?.radius }) local resource = GetInvokingResource() local handler handler = AddEventHandler("onResourceStop", function(resName) if resName ~= resource then return end RemoveEventHandler(handler) exports["qb-target"]:RemoveZone(zoneId) end) end } ``` Adds interaction to passed models. ### Parameters * models: number\[] * entries: [Entry](#entry)\[] * options:[ Options](#options) Adds interaction for sphere zone. ### Parameters * coords: vector3 * radius: number * entries: [Entry](#entry)\[] * options:[ Options](#options) # Inventory Source: https://docs.nonefivem.com/scripts/no-base/configuration/inventory If you're using [supported inventory](/no-base/supported-resources) you dont have to make any changes in this section. > You can override inventory actions from `no-base/configure/server/inventory.lua` ## Examples *** This is an example of how we handle qb-inventory. Since we support qb-inventory internally you don't need to make any changes if you use qb-inventory. ```lua theme={null} local core = exports["qb-core"]:GetCoreObject() local GetPlayer = core.Functions.GetPlayer local RegisterItem = core.Functions.CreateUseableItem core = nil Config.Inventory = { RegisterItem = function(itemName, cb) RegisterItem(itemName, function(source, item) item.metadata, item.info = item.info or item.metadata, nil cb(source, item) end) end, AddItem = function(source, itemName, count, metadata) local player = GetPlayer(source) if not player then return false end return player.Functions.AddItem(itemName, count, false, metadata) end, RemoveItem = function(source, itemName, count) local player = GetPlayer(source) if not player then return false end return player.Functions.RemoveItem(itemName, count) end } ``` Registers item to the inventory. ### Parameters * itemName: string * cb: `Function(source: number, item: {metadata: any})` Adds item to the given source's inventory. ### Parameters * source: number * itemName: string * count: number * metadata?: any ### Returns * success: boolean Removes item to the given source's inventory. ### Parameters * source: number * itemName: string * count: number ### Returns * success: boolean # Media Upload Source: https://docs.nonefivem.com/scripts/no-base/configuration/media-upload Configure how screenshots and media files are uploaded ## Overview The media upload system allows you to configure where screenshots and other media files are uploaded. This is configured in `no-base/configure/shared/sh_main.lua` under the `MediaUpload` section. All uploads go directly from the client to the provider to avoid unnecessary server load. For cloud providers, we use signed URLs to keep your API keys secure on the server side. ## Configuration ```lua theme={null} MediaUpload = { provider = "nocloud", --- If using Discord as the provider, set the webhook URL here. discord = { webhook_url = nil } }, ``` ## Available Providers ### NoCloud (`nocloud`) NoneM's cloud storage solution. This is the default **recommended** provider and works out of the box with NoneM scripts. * Fast uploads with global CDN * API keys stay secure on the server * Free tier available Get started at [dash.nonefivem.com](https://dash.nonefivem.com) or see the [Cloud Documentation](/cloud). **Requirements:** * Requires [no-cloud-cfx](https://github.com/nonefivem/no-cloud-cfx) resource. See [installation](/cloud/sdks/cfx/installation). **Configuration:** ```lua theme={null} MediaUpload = { provider = "nocloud" } ``` ### File Server (`no-file-server`) Upload files directly to your own server. Requires self-hosting and maintenance. **Requirements:** * Requires [cfx-file-server](https://github.com/nonefivem/cfx-file-server) resource * Server with sufficient storage and bandwidth * Technical knowledge to set up and maintain **Configuration:** ```lua theme={null} MediaUpload = { provider = "no-file-server" } ``` ### Imgbox (`imgbox`) Free image hosting service. No API key required, but it's extremely slow and comes with no SLA (Service Level Agreement). **Configuration:** ```lua theme={null} MediaUpload = { provider = "imgbox" } ``` Imgbox is extremely slow and unreliable. Only use this for testing purposes. ### FiveManage (`fivemanage`) Cloud storage provider with reliable hosting. Both free and paid plans available. **Requirements:** * Requires `NO_FIVEMANAGE_MEDIA_API_KEY` or `FIVEMANAGE_MEDIA_API_KEY` convar **Configuration:** ```lua theme={null} MediaUpload = { provider = "fivemanage" } ``` Add to your `server.cfg`: ```cfg theme={null} set NO_FIVEMANAGE_MEDIA_API_KEY "your_api_key_here" # or set FIVEMANAGE_MEDIA_API_KEY "your_api_key_here" ``` ### Discord Webhook (`discord`) Upload images to a Discord channel via webhook. Image links are not permanent and may change or expire. **Configuration:** ```lua theme={null} MediaUpload = { provider = "discord", discord = { webhook_url = "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL" } } ``` Discord webhooks are exposed to the client. Use with caution and consider the security implications. The webhook URL will be visible in client-side code. Additionally, image links are not permanent and may change or expire, making this unsuitable for long-term storage. ## Security Considerations * **Cloud Providers (nocloud, fivemanage)**: API keys are kept secure on the server side through signed URLs * **Discord**: Webhook URLs are exposed to the client - anyone with access to the client files can see and potentially abuse the webhook * **Direct Client Uploads**: All providers upload directly from the client to reduce server load ## Choosing a Provider | Provider | Speed | Reliability | Security | Cost | Best For | | -------------- | --------- | ----------- | ---------------------- | ------------------ | ----------------------------- | | nocloud ⭐ | Fast | High | Excellent | Free & Paid | Production servers | | no-file-server | Fast | Medium | Excellent | Free (self-hosted) | Full control, private servers | | fivemanage | Fast | High | Excellent | Free & Paid | Alternative cloud option | | imgbox | Very Slow | Low | Good | Free | Not recommended | | discord | Fast | Low | Poor (webhook exposed) | Free | Testing only | **Our Recommendation:** Use **NoCloud** for the best experience with NoneM scripts. It's designed to work seamlessly with all our resources and requires minimal setup. **Not recommended for production:** `imgbox`, `discord` # Player Management Source: https://docs.nonefivem.com/scripts/no-base/configuration/player-management If you're using [supported framework](/no-base/supported-resources#frameworks) you dont have to make any changes in this section. > You can override player actions from `no-base/configure/server/player.lua` ## Examples *** ```lua theme={null} Config.Player = { ---@param source number ---@return string | number GetIdentifier = function(source) return GetPlayerIdentifierByType(source, "steam") or GetPlayerIdentifierByType(source, "license") or GetPlayerIdentifierByType(source, "license2") end, ---@param identifier string ---@return number | nil GetSourceByIdentifier = function(identifier) local GetPlayerIdentifierByType = GetPlayerIdentifierByType for _, playerId in ipairs(GetPlayers()) do if GetPlayerIdentifierByType(playerId, "steam") == identifier or GetPlayerIdentifierByType(playerId, "license") == identifier or GetPlayerIdentifierByType(playerId, "license2") == identifier then return playerId end end return nil end, ---@param source number ---@return string GetFullname = function(source) return GetPlayerName(source) end, ---@return number[] GetLoadedPlayers = function() local players = {} for playerId in pairs(exports.qbx_core:GetQBPlayers()) do players[#players + 1] = playerId end return players end ---@param cb fun(source: number): void ---@return void OnPlayerLoaded = function(cb) AddEventHandler("QBCore:Server:PlayerLoaded", function(player) cb(player.PlayerData.source) end) end, ---@param cb fun(source: number): void ---@return void OnPlayerUnload = function(cb) AddEventHandler("QBCore:Server:OnPlayerUnload", function(source) cb(source) end) end, ---@param source number ---@param amount number ---@param reason string | nil ---@return boolean AddBank = function(source, amount, reason) return true end, ---@param source number ---@param amount number ---@param reason string | nil ---@return boolean RemoveBank = function(source, amount, reason) return true end, ---@param source number ---@param amount number ---@param reason string | nil ---@return boolean AddMoney = function(source, amount, reason) return true end, ---@param source number ---@param amount number ---@param reason string | nil ---@return boolean RemoveMoney = function(source, amount, reason) return true end } ``` Should return unique id for the players current character. (E.g. citizenid on QB identifier on ESX) ### Parameters * source: number ### Returns * identifier: string | number Should return the player id if player is online by provided identifier with GetIdentifier method. ### Parameters * identifier: string ### Returns * playerServerId: number (source) Should return fullname of the player character. ### Parameters * source: number ### Returns * fullname: string Should return array of loaded player server ids. ### Returns * playerIds: number\[] Should add event handler that will execute the callback whenever the player is loaded. ### Parameters * cb: func(source: number) Should add event handler that will execute the callback whenever the player is unloaded. ### Parameters * cb: func(source: number) Adds money to player bank account. ### Parameters * source: number * amount: number * reason?: string ### Returns * success: boolean Removes money from player bank account. ### Parameters * source: number * amount: number * reason?: string ### Returns * success: boolean Adds money to player inventory. ### Parameters * source: number * amount: number * reason?: string ### Returns * success: boolean Removes money from player inventory. ### Parameters * source: number * amount: number * reason?: string ### Returns * success: boolean # UI Source: https://docs.nonefivem.com/scripts/no-base/configuration/ui ## Theming *** You can find the themes in `no-base/configure/ui/themes.json`. The active theme will be applied to all other NoneM resources to ensure consistency. You can create multiple themes, but make sure the **active theme name** matches the one you want to use. # Introduction Source: https://docs.nonefivem.com/scripts/no-base/index This resource comes with other products. Not for sale. ## Installation * Download no-base from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Create `[none]` folder in resources. * Drag & drop no-base to folder you just created. * Add `ensure no-base` in your server.cfg after framework and other core scripts like inventory, target etc. (if you are using one) Make sure no-base is starting before the other NoneM resources. # Supported Resources Source: https://docs.nonefivem.com/scripts/no-base/supported-resources ### Framework *** * [ESX Legacy](https://github.com/esx-framework/esx_core) * [QB Core](https://github.com/qbcore-framework/qb-core/) * [Qbox](https://github.com/Qbox-project/qbx_core) ### MySQL *** * [oxmysql](https://github.com/overextended/oxmysql) * [mysql-async](https://github.com/brouznouf/fivem-mysql-async) ### Inventory *** If your inventory work through [supported framework](#framework), we support them too. * [ox\_inventory](https://github.com/overextended/ox_inventory) * [qb-inventory](https://github.com/qbcore-framework/qb-inventory) * [tgiann-inventory](https://docs.tgiann.com/scripts/tgiann-inventory) * [codem-inventory](https://codem.gitbook.io/codem-documentation/m-series/essentials/minventory-remake) * [jaksam\_inventory](https://documentation.jaksam-scripts.com/jaksam-inventory) ### Interact (Target) *** * [ox\_target](https://github.com/overextended/ox_target) * [qb-target](https://github.com/qbcore-framework/qb-target) ### Context Menu *** * [ox\_lib](https://github.com/overextended/ox_lib) * [qb-menu](https://github.com/qbcore-framework/qb-menu) * [qb-input](https://github.com/qbcore-framework/qb-input) * [esx\_context](https://github.com/esx-framework/esx_core/tree/main/\[core]/esx_context) # Client Events Source: https://docs.nonefivem.com/scripts/no-camera/api/client-events Documentation for client-side events. ## no-camera:camera:state\_changed Triggered when the camera state changes. ```lua theme={null} ---@enum CAMERA_STATE CAMERA_STATE = { DEACTIVE = 0, -- Camera is inactive HOLDING = 1, -- Camera is being held VIEWING = 2, -- Viewing through the camera PHOTO_MODE = 3 -- In photo mode } ---@param new_state CAMERA_STATE - The new camera state ---@param old_state CAMERA_STATE - The previous camera state AddEventHandler("no-camera:camera:state_changed", function(new_state, old_state) print(("Camera state changed from %s to %s"):format(old_state, new_state)) end) ``` ## no-camera:camera:activated Triggered when the camera is activated. ```lua theme={null} AddEventHandler("no-camera:camera:activated", function() print("Camera activated") end) ``` ## no-camera:camera:deactivated Triggered when the camera is deactivated. ```lua theme={null} AddEventHandler("no-camera:camera:deactivated", function() print("Camera deactivated") end) ``` ## no-camera:camera:taking\_photo Triggered when the camera is taking a photo. ```lua theme={null} ---@class CameraSettings ---@field iso number ---@field iso_idx number ---@field shutter_speed string ---@field shutter_speed_idx number ---@field aperture number ---@field aperture_idx number ---@field zoom_level number ---@field zoom_idx number ---@field flash_mode string ---@field flash_mode_idx number ---@param settings CameraSettings - The current camera settings AddEventHandler("no-camera:camera:taking_photo", function(settings) print("Taking photo with current settings") end) ``` ## no-camera:camera:photo\_complete Triggered when the photo capture is complete. ```lua theme={null} ---@param success boolean - Whether the photo capture was successful AddEventHandler("no-camera:camera:photo_complete", function(success) print(("Photo capture %s"):format(success and "succeeded" or "failed")) end) ``` ## no-camera:photo\_mode:activated Triggered when photo mode is activated. ```lua theme={null} AddEventHandler("no-camera:photo_mode:activated", function() print("Photo mode activated") end) ``` ## no-camera:photo\_mode:deactivated Triggered when photo mode is deactivated. ```lua theme={null} AddEventHandler("no-camera:photo_mode:deactivated", function() print("Photo mode deactivated") end) ``` ## no-camera:settings:changed Triggered when a camera setting is changed. ```lua theme={null} ---@class CameraSettings ---@field iso number ---@field iso_idx number ---@field shutter_speed string ---@field shutter_speed_idx number ---@field aperture number ---@field aperture_idx number ---@field zoom_level number ---@field zoom_idx number ---@field flash_mode string ---@field flash_mode_idx number ---@param setting string - The setting that was changed ---@param value any - The new value of the setting AddEventHandler("no-camera:settings:changed", function(setting, value) print(("Setting %s changed to %s"):format(setting, tostring(value))) end) ``` ## no-camera:settings:reset Triggered when camera settings are reset to defaults. ```lua theme={null} AddEventHandler("no-camera:settings:reset", function() print("Camera settings reset to defaults") end) ``` ## no-camera:nui:view\_changed Triggered when the NUI view changes. ```lua theme={null} ---@enum CameraNUIView CAMERA_NUI_VIEW = { MENU = "menu", VIEWFINDER = "viewfinder", GALLERY = "gallery", SETTINGS = "settings" } ---@param view CameraNUIView - The new NUI view ---@param old_view CameraNUIView - The previous NUI view AddEventHandler("no-camera:nui:view_changed", function(view, old_view) print(("View changed from %s to %s"):format(old_view, view)) end) ``` ## no-camera:nui:activated Triggered when the NUI is activated. ```lua theme={null} AddEventHandler("no-camera:nui:activated", function() print("NUI activated") end) ``` ## no-camera:nui:deactivated Triggered when the NUI is deactivated. ```lua theme={null} AddEventHandler("no-camera:nui:deactivated", function() print("NUI deactivated") end) ``` ## no-camera:photo:shown Triggered when a photo is shown. **Payload** * photo: table - The photo being shown ```lua theme={null} AddEventHandler("no-camera:photo:shown", function(photo) print(("Showing photo %s"):format(photo.id)) end) ``` ## no-camera:photo:closed Triggered when a photo is closed. **Payload** * photo: table - The photo that was closed ```lua theme={null} AddEventHandler("no-camera:photo:closed", function(photo) print(("Closed photo %s"):format(photo.id)) end) ``` # Client Exports Source: https://docs.nonefivem.com/scripts/no-camera/api/client-exports Documentation for client-side exports. ## Camera State ### is\_camera\_active Checks if the camera is currently active (holding, viewing, or photo mode). ```lua theme={null} ---@return boolean is_active local is_active = exports["no-camera"]:is_camera_active() ``` ### get\_camera\_state Gets the current camera state. ```lua theme={null} ---@enum CAMERA_STATE CAMERA_STATE = { DEACTIVE = 0, HOLDING = 1, VIEWING = 2, PHOTO_MODE = 3 } ---@return CAMERA_STATE state local state = exports["no-camera"]:get_camera_state() ``` ### is\_photo\_mode Checks if the player is currently in photo mode (viewfinder active). ```lua theme={null} ---@return boolean is_photo_mode local is_photo_mode = exports["no-camera"]:is_photo_mode() ``` ### is\_viewing\_mode Checks if the player is currently viewing the camera menu. ```lua theme={null} ---@return boolean is_viewing local is_viewing = exports["no-camera"]:is_viewing_mode() ``` ### is\_taking\_photo Checks if a photo is currently being taken. ```lua theme={null} ---@return boolean is_taking_photo local is_taking = exports["no-camera"]:is_taking_photo() ``` ## Camera Control ### activate\_camera Activates the camera (enters holding state). ```lua theme={null} exports["no-camera"]:activate_camera() ``` ### deactivate\_camera Deactivates the camera completely. ```lua theme={null} exports["no-camera"]:deactivate_camera() ``` ### toggle\_camera Toggles the camera on/off. ```lua theme={null} ---@return boolean is_active Returns true if camera is now active local is_active = exports["no-camera"]:toggle_camera() ``` ### enter\_photo\_mode Enters photo mode (viewfinder). ```lua theme={null} ---@return boolean success ---@return string? error Error message if failed local success, error = exports["no-camera"]:enter_photo_mode() ``` ### exit\_photo\_mode Exits photo mode (returns to holding state). ```lua theme={null} exports["no-camera"]:exit_photo_mode() ``` ### toggle\_photo\_mode Toggles photo mode on/off. ```lua theme={null} ---@return boolean is_photo_mode local is_photo_mode = exports["no-camera"]:toggle_photo_mode() ``` ### enter\_viewing\_mode Enters viewing mode (camera menu). ```lua theme={null} exports["no-camera"]:enter_viewing_mode() ``` ### exit\_viewing\_mode Exits viewing mode (returns to holding state). ```lua theme={null} exports["no-camera"]:exit_viewing_mode() ``` ### toggle\_viewing\_mode Toggles viewing mode on/off. ```lua theme={null} exports["no-camera"]:toggle_viewing_mode() ``` ### take\_photo Takes a photo (must be in photo mode). ```lua theme={null} ---@return boolean success ---@return string? error Error message if failed local success, error = exports["no-camera"]:take_photo() ``` ## Camera Settings ### get\_camera\_settings Gets all current camera settings. ```lua theme={null} ---@class CameraSettingsData ---@field iso number ---@field shutter_speed string ---@field aperture number ---@field zoom_level number ---@field flash_mode string ---@return CameraSettingsData settings local settings = exports["no-camera"]:get_camera_settings() ``` ### set\_iso Sets the camera ISO value. ```lua theme={null} ---@param value number ISO value (100, 200, 400, 800, 1600, 3200, 6400) ---@return boolean success local success = exports["no-camera"]:set_iso(400) ``` ### set\_shutter\_speed Sets the camera shutter speed. ```lua theme={null} ---@param value string Shutter speed ("1/4000", "1/2000", "1/1000", "1/500", "1/250", "1/125", "1/60", "1/30", "1/15", "1/8", "1/4", "1/2", "1") ---@return boolean success local success = exports["no-camera"]:set_shutter_speed("1/250") ``` ### set\_aperture Sets the camera aperture. ```lua theme={null} ---@param value number Aperture value (1.4, 2, 2.8, 4, 5.6, 8, 11, 16, 22) ---@return boolean success local success = exports["no-camera"]:set_aperture(2.8) ``` ### set\_zoom Sets the camera zoom level. ```lua theme={null} ---@param value number Zoom level (1, 1.5, 2, 3, 5, 10) ---@return boolean success local success = exports["no-camera"]:set_zoom(2) ``` ### set\_flash\_mode Sets the camera flash mode. ```lua theme={null} ---@param value string Flash mode ("auto", "on", "off") ---@return boolean success local success = exports["no-camera"]:set_flash_mode("auto") ``` ### update\_camera\_settings Updates multiple camera settings at once. ```lua theme={null} ---@param settings table Settings to update (iso, shutter_speed, aperture, zoom_level, flash_mode) ---@return table result { success = table, settings = table } local result = exports["no-camera"]:update_camera_settings({ iso = 800, aperture = 4, flash_mode = "on" }) ``` ### reset\_camera\_settings Resets all camera settings to defaults. ```lua theme={null} exports["no-camera"]:reset_camera_settings() ``` ## Photo Display ### show\_photo Shows a photo in the player's hand. ```lua theme={null} ---@param image string URL of the photo ---@param location string? Optional location string ---@param timestamp number? Optional timestamp exports["no-camera"]:show_photo("https://example.com/photo.jpg", "Vinewood Hills", 1738656000000) ``` ### close\_photo Closes the currently displayed photo. ```lua theme={null} exports["no-camera"]:close_photo() ``` ### is\_photo\_active Checks if a photo is currently being displayed. ```lua theme={null} ---@return boolean is_active local is_active = exports["no-camera"]:is_photo_active() ``` ### focus\_photo Focuses the current photo in fullscreen NUI view. ```lua theme={null} exports["no-camera"]:focus_photo() ``` ### unfocus\_photo Unfocuses the current photo from fullscreen view. ```lua theme={null} exports["no-camera"]:unfocus_photo() ``` ### is\_photo\_focused Checks if the photo is currently focused in fullscreen. ```lua theme={null} ---@return boolean is_focused local is_focused = exports["no-camera"]:is_photo_focused() ``` ### get\_current\_photo Gets the current photo data. ```lua theme={null} ---@class PhotoData ---@field image string URL of the photo ---@field location? string Location where the photo was taken ---@field timestamp? number Unix timestamp when the photo was taken ---@return PhotoData? photo The current photo data or nil if none local photo = exports["no-camera"]:get_current_photo() ``` # Server Events Source: https://docs.nonefivem.com/scripts/no-camera/api/server-events Documentation for server-side events. ## no-camera:gallery:photo:created Triggered when a new photo is created in the gallery. ```lua theme={null} ---@class Photo ---@field id number ---@field owner_identifier string ---@field url string ---@field location string ---@field created_at number ---@param photo Photo - The newly created photo AddEventHandler("no-camera:gallery:photo:created", function(photo) print(("New photo created with ID: %d by user: %s"):format(photo.id, photo.owner_identifier)) end) ``` ## no-camera:gallery:photo:deleted Triggered when a photo is deleted from the gallery. ```lua theme={null} ---@param photo_id number - The ID of the deleted photo AddEventHandler("no-camera:gallery:photo:deleted", function(photo_id) print(("Photo deleted with ID: %d"):format(photo_id)) end) ``` ## no-camera:gallery:photo:shared Triggered when a photo is shared with another player. ```lua theme={null} ---@class PhotoShareDTO ---@field id number ---@field owner_identifier string ---@field url string ---@field location string ---@field created_at number ---@field new_photo_id number ---@field target_identifier string ---@param photo PhotoShareDTO - The shared photo details AddEventHandler("no-camera:gallery:photo:shared", function(photo) print(("Photo %d shared with: %s by: %s"):format(photo.id, photo.target_identifier, photo.owner_identifier)) end) ``` # Server Exports Source: https://docs.nonefivem.com/scripts/no-camera/api/server-exports Documentation for server-side exports. ## Gallery Management ### save\_photo Saves a photo to a player's gallery. ```lua theme={null} ---@param owner_identifier string The player's identifier ---@param url string The photo URL ---@param location string? Optional location where the photo was taken ---@return number? photo_id The ID of the saved photo, or nil on failure local photo_id = exports["no-camera"]:save_photo("license:abc123", "https://example.com/photo.jpg", "Vinewood Hills") ``` ### get\_photo Gets a photo by its ID. ```lua theme={null} ---@class GalleryItem ---@field id number ---@field owner_identifier string ---@field url string ---@field location string ---@field created_at number ---@param photo_id number The photo ID ---@return GalleryItem? photo The photo data or nil if not found local photo = exports["no-camera"]:get_photo(1) ``` ### get\_photos\_by\_owner Gets a list of photos for a player with pagination. ```lua theme={null} ---@class GalleryItemPaginationResults ---@field total number ---@field page number ---@field page_size number ---@field has_more boolean ---@field results table ---@param owner_identifier string The player's identifier ---@param page number Page number (1-based) ---@param page_size number Number of photos per page ---@param search string? Optional search term to filter by location ---@return GalleryItemPaginationResults results Paginated photo results local results = exports["no-camera"]:get_photos_by_owner("license:abc123", 1, 10, nil) -- Example response: -- { -- total = 25, -- page = 1, -- page_size = 10, -- has_more = true, -- results = { ... } -- } ``` ### delete\_photo Deletes a photo from the gallery. ```lua theme={null} ---@param photo_id number The photo ID to delete ---@param owner_identifier string? Optional owner identifier (if provided, only deletes if owned by this player) ---@return boolean success True if deleted local success = exports["no-camera"]:delete_photo(1, "license:abc123") ``` ### share\_photo Shares a photo with another player (copies it to their gallery). ```lua theme={null} ---@param photo_id number The photo ID to share ---@param target_identifier string The target player's identifier ---@param owner_identifier string? Optional owner identifier for verification ---@return boolean success True if shared successfully local success = exports["no-camera"]:share_photo(1, "license:xyz789", "license:abc123") ``` ## Inventory Integration ### give\_photo\_item Adds a physical photo item to a player's inventory. ```lua theme={null} ---@param source number The player server ID ---@param image string The photo URL ---@param location string? Optional location string ---@param timestamp number? Optional timestamp when photo was taken ---@return boolean success True if item was added ---@return string? error Error message if failed local success, error = exports["no-camera"]:give_photo_item(1, "https://example.com/photo.jpg", "Vinewood Hills", 1738656000000) ``` ### is\_inventory\_enabled Checks if inventory integration is enabled. ```lua theme={null} ---@return boolean enabled local enabled = exports["no-camera"]:is_inventory_enabled() ``` ## Player Camera State ### is\_player\_camera\_active Checks if a player has their camera active (via state bag). ```lua theme={null} ---@param source number The player server ID ---@return boolean is_active True if camera is active local is_active = exports["no-camera"]:is_player_camera_active(1) ``` ### get\_player\_camera\_state Gets a player's current camera state (via state bag). ```lua theme={null} ---@enum CAMERA_STATE CAMERA_STATE = { DEACTIVE = 0, HOLDING = 1, VIEWING = 2, PHOTO_MODE = 3 } ---@param source number The player server ID ---@return CAMERA_STATE? state The camera state or nil if player not found local state = exports["no-camera"]:get_player_camera_state(1) ``` # Configuration Source: https://docs.nonefivem.com/scripts/no-camera/configuration Configure no-camera settings. Configuration can be found in `no-camera/config/shared.lua`. For media upload provider settings, refer to [Media Upload Configuration](/scripts/no-base/configuration/media-upload). ## Inventory Configure inventory integration for camera and photo items. ```lua theme={null} Config.Inventory = { enabled = true, -- Whether inventory integration is enabled camera_item = "camera", -- Item name for the camera photo_item = "cam_photo" -- Item name for the photo } ``` | Option | Type | Default | Description | | ------------- | ------- | ------------- | ---------------------------------------- | | `enabled` | boolean | `true` | Whether inventory integration is enabled | | `camera_item` | string | `"camera"` | Item name for the camera | | `photo_item` | string | `"cam_photo"` | Item name for the photo | ## Indicators Configure the keybind indicators shown when the camera is first activated. ```lua theme={null} Config.Indicators = { enabled = true, -- Whether the indicators are enabled timeout = 5000 -- Time in milliseconds before the indicators are hidden } ``` | Option | Type | Default | Description | | --------- | ------- | ------- | ----------------------------------------------------- | | `enabled` | boolean | `true` | Whether the indicators are enabled | | `timeout` | number | `5000` | Time in milliseconds before the indicators are hidden | ## Keybinds Configure default keybinds for camera actions. If you change these keybinds, they won't be updated for players who already have keybinds set. Players can change their keybinds in the settings menu. ```lua theme={null} Config.Keybinds = { DEACTIVATE = "BACK", -- Key to deactivate the camera VIEW = "G", -- Key to toggle camera view PHOTO_MODE = "E", -- Key to toggle photo mode TAKE_PHOTO = "MOUSE_LEFT", -- Key to take a photo HOLD_HELP = "H", -- Key to hold for camera controls help PHOTO_FOCUS = "E", -- Key to view photo in fullscreen PHOTO_CLOSE = "BACK" -- Key to close the photo } ``` | Option | Type | Default | Description | | ------------- | ------ | -------------- | ------------------------------------ | | `DEACTIVATE` | string | `"BACK"` | Key to deactivate the camera | | `VIEW` | string | `"G"` | Key to toggle camera view | | `PHOTO_MODE` | string | `"E"` | Key to toggle photo mode | | `TAKE_PHOTO` | string | `"MOUSE_LEFT"` | Key to take a photo | | `HOLD_HELP` | string | `"H"` | Key to hold for camera controls help | | `PHOTO_FOCUS` | string | `"E"` | Key to view photo in fullscreen | | `PHOTO_CLOSE` | string | `"BACK"` | Key to close the photo | ## Integrations Enable or disable third-party integrations. See [Integrations](/scripts/no-camera/integrations) for more details. ```lua theme={null} Config.Integrations = { LBPhone = { enabled = true } } ``` | Integration | Default | Description | | ----------------- | ------- | ------------------------------------------------------------------- | | `LBPhone.enabled` | `true` | Enable LB Phone integration to add photos to player's phone gallery | # Introduction Source: https://docs.nonefivem.com/scripts/no-camera/index A complete in-game camera that creates real photo objects and synced UI instead of just screenshots. [Tebex Page](https://store.nonefivem.com/packages/no-camera). ### Installation 1. Make sure you've installed [no-base](https://docs.nonefivem.com/no-base/#installation) correctly. 2. Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). 3. Drag & drop your resource to `resources/[none]` 4. Add `ensure no-camera` to your server.cfg after no-base. # Custom Integrations Source: https://docs.nonefivem.com/scripts/no-camera/integrations/custom Create your own integrations for no-camera. You can create your own custom integrations to extend no-camera functionality. Integration files are not encrypted and can be used as reference for building your own. ## Getting Started 1. Create a new Lua file in `no-camera/integrations/` folder 2. Use the available [events](/scripts/no-camera/api/client-events) and [exports](/scripts/no-camera/api/client-exports) to hook into camera functionality 3. Reference existing integrations like `lb-phone.lua` for examples Integration files run on both client and server. Use the `_IS_SERVER` global to determine the current environment. ```lua theme={null} if _IS_SERVER then -- Server-side code AddEventHandler("no-camera:gallery:photo:created", function(photo) -- Handle server-side logic end) else -- Client-side code AddEventHandler("no-camera:camera_manager:photo_complete", function(success) -- Handle client-side logic end) end ``` ## Available Hooks ### Client Events Use client events to react to camera state changes, photo captures, and UI interactions. See the full list in [Client Events](/scripts/no-camera/api/client-events). ### Server Events Use server events to react to gallery changes like photo creation, deletion, and sharing. See the full list in [Server Events](/scripts/no-camera/api/server-events). ### Exports Use exports to programmatically control camera functionality. See [Client Exports](/scripts/no-camera/api/client-exports) and [Server Exports](/scripts/no-camera/api/server-exports). ## Tips * Look at existing third-party integrations in the `integrations` folder for reference * Keep your integration modular and self-contained * Use the configuration pattern from other integrations (`Config.Integrations.YourIntegration.enabled`) * Check if required resources exist before initializing your integration # LB Phone Source: https://docs.nonefivem.com/scripts/no-camera/integrations/lb-phone Integration details for LB Phone with no-camera. LB Phone integration is enabled by default. Captured photos will automatically be added to the player's phone gallery. If LB Phone is not found on the server, the integration will not be initialized. ## Configuration You can enable or disable the integration in `no-camera/config/shared.lua`: ```lua theme={null} Config.Integrations.LBPhone.enabled = false ``` ## Integration File The integration file is located at `no-camera/integrations/lb-phone.lua`. This file is not encrypted and can be edited to customize the integration behavior. # Configuration Source: https://docs.nonefivem.com/scripts/no-chains/configuration ## Options *** Options can be found in `no-chains/config/shared/chains.lua` | Option | type | Description | | ------------- | ------- | ---------------------------------------------------- | | Duration | number | How long the effect will last. (milliseconds) | | Interval | number | Interval of effect appearance (milliseconds) | | Chance | number | Chance of the effect appearing per interval. (0-100) | | PlayAnimation | boolean | | ## Adding As Item *** If you are using [supported framework](/no-base/supported-resources#frameworks) you can set item name from `no-chains/config/shared/chains.lua` or you can trigger `no-chains:equip` event on the client. ## Effects *** You can add as many effects as you want. [Effect List](https://vespura.com/fivem/particle-list/). ### Effect *** | Field | Type | Description | | ------ | ------ | -------------------------- | | dict | string | Dictionary of the particle | | effect | string | Name of the particle | | size | number | Size of the effect | # Exports & Events Source: https://docs.nonefivem.com/scripts/no-chains/exports-and-events ## Client Net Events Toggles chain. Equips chain. Removes chain. # Introduction Source: https://docs.nonefivem.com/scripts/no-chains/index FiveM resource for chains with effects. [Tebex Page](https://store.nonefivem.com/packages/5935610). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-chains` to your server cfg after no-base. # Contextmenu Usage Source: https://docs.nonefivem.com/scripts/no-contextmenu/context-menu-usage ## Types *** ### Button Data
FieldTypeDescriptionRequired
headerstringtrue
textstringfalse
onClickstringEvent to triggerfalse
leftIconstringFont Awesome Icon Namefalse
rightIconstringFont Awesome Icon Namefalse
dataanyData to pass when triggering onClick eventfalse
iconColorstringColor hexfalse
subMenuMenu DataCreates sub menu on clickfalse
confirmConfirm Menu DataCreates confirm menu on clickfalse
disabledbooleanDisables buttonfalse
### Menu Data
FieldTypeDescriptionRequired
itemsButton Data\[]true
onClosestringEvent to trigger if menu is closedfalse
### Confirm Menu Data
FieldTypeDescriptionRequired
headerstringtrue
textstringfalse
onCancelstringEvent to trigger on cancel button clickedfalse
onConfirmstringEvent to trigger on confirm button clickedfalse
rightIconstringFont Awesome Icon Namefalse
leftIconstringFont Awesome Icon Namefalse
dataanyData to pass when triggering on cancel or on confirm events (if undefined it will take parents data)false
## Examples *** ### Creating Contextmenu ```lua theme={null} local menu = { items = { { header = "User Info", leftIcon = "user" }, { header = "Location", text = "x = 0.0, y = 0.0, z = 0.0", leftIcon = "location-dot", onClick = "print", data = "coords" }, { header = "Heading", text = "180.0", leftIcon = "compass", onClick = "print", data = "heading" } } } exports["no-contextmenu"]:CreateMenu(menu) ``` ### Handling Onclick Events ```lua theme={null} AddEventHandler("print", function(data) if data == "heading" then return print(GetEntityHeading(PlayerPedId())) end if data == "coords" then return print(GetEntityCoords(PlayerPedId())) end end) ``` ### Dynamic Submenus ```lua theme={null} local users = {"Kyle", "Alice"} AddEventHandler("users:menu", function() local menu = { items = {} } for _, user in pairs(users) do menu.items[#menu.items + 1] = { header = user, leftIcon = "user", rightIcon = "chevron-right", onClick = "user:menu", data = user } end -- Creates new menu based on users -- Sorts menu by usernames exports["no-contextmenu"]:CreateMenu(menu, true) end) AddEventHandler("user:menu", function(userName) local userData = fetchUser(userName) -- fetchs user based on passed data local menu = { items = { { header = userName, leftIcon = "user" }, { header = "Age", text = userData.age }, { header = "Phone", text = userData.phoneNumber } } } -- creates sub menu based on last opened menu exports["no-contextmenu"]:CreateSubMenu(menu) end) ``` # Exports Source: https://docs.nonefivem.com/scripts/no-contextmenu/exports Creates new menu. See [Creating ContextMenu](/no-contextmenu/context-menu-usage#creating-contextmenu). **Parameters** * menu: [Menu data](/no-contextmenu/context-menu-usage#menu-data) * sort?: boolean (Sorts items based on header) Creates sub menu based on last opened menu. See [Dynamic Submenus](/no-contextmenu/context-menu-usage#dynamic-submenus). **Parameters** * menu: [Menu data](/no-contextmenu/context-menu-usage#menu-data) * sort?: boolean (Sorts items based on header) Creates input menu. See [Creating Input Menu](/no-contextmenu/input-menu-usage#creating-input-menu). **Parameters** * menu: [Input Menu Data](/no-contextmenu/input-menu-usage#input-menu-data) ### Returns * values?: any\[] (Row values in order) # Introduction Source: https://docs.nonefivem.com/scripts/no-contextmenu/index FiveM resource for creating context & inputmenu. [Tebex Page](https://store.nonefivem.com/packages/5869910). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-contextmenu` to your server.cfg after no-base. # Input Menu Usage Source: https://docs.nonefivem.com/scripts/no-contextmenu/input-menu-usage ## Types *** ### Input Types * text * number * select * radio * checkbox * slider ### Choice
FieldTypeRequired
labelstringtrue
valueanyfalse
### Row Data
FieldTypeRequired
typeInput Typesfalse
labelstringfalse
placeholderstringfalse
leftIconstringfalse
rightIconstringfalse
valueanyfalse
choicesChoice\[]false
### Input Menu Data
FieldTypeRequired
headerstringfalse
leftIconstringfalse
rightIconstringfalse
rowsRow Datatrue
## Examples *** ### Creating Input Menu ```lua theme={null} local inputMenuData = { leftIcon = "envelope", header = "Mail", rows = { { label = "To", placeholder = "5XX-XXXX", type = "text" }, { label = "Content" } } } local inputMenu = exports["no-contextmenu"]:CreateInputMenu(inputMenuData) -- menu closed if not inputMenu then return end local to, content = table.unpack(inputMenu) ``` # Door Selector Source: https://docs.nonefivem.com/scripts/no-elevators/configuration/door-selector ## Options *** You can find config file in `no-elevators/config/sh_door.selector.lua` | Option | type | Description | | -------- | ----------------------- | -------------------------------------------------------------------------------------------- | | keybinds | \[key: string]: string; | [Keybinds](https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/) | # Elevator Creator Source: https://docs.nonefivem.com/scripts/no-elevators/configuration/elevator-creator ## Options *** You can find config file in `no-elevators/config/sh_elevator.creator.lua` | Option | type | Description | | ---------- | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | command | string | The command to open the elevator creator menu. | | permission | string? | [Access Control Commands](https://docs.fivem.net/docs/server-manual/server-commands/#access-control-commands) | | keybinds | \[key: string]: string; | [Keybinds](https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/) | # Floor Creator Source: https://docs.nonefivem.com/scripts/no-elevators/configuration/floor-creator ## Options *** You can find config file in `no-elevators/config/sh_floor.creator.lua` | Option | type | Description | | -------- | ----------------------- | -------------------------------------------------------------------------------------------- | | keybinds | \[key: string]: string; | [Keybinds](https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/) | # Icons Source: https://docs.nonefivem.com/scripts/no-elevators/configuration/icons ## Options *** You can find config file in `no-elevators/config/sh_icons.lua` | Option | type | Description | | ------ | ----------------------- | ------------------------------------------------- | | Icons | \[key: string]: string; | [Icons](https://fontawesome.com/v6/search?m=free) | # Configuration Source: https://docs.nonefivem.com/scripts/no-elevators/configuration/index ## Options *** You can find config file in `no-elevators/config/sh_config.lua` | Option | type | Description | | ---------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | EnableDefaultSceneIplLoading | boolean | It will load the FIB ipl on default scene usage if you're not using a custom ipl loader. If you change the default scene it won't load the FIB ipl. | | DefaultFloorTransitionTime | number | The default time it takes for the elevator to travel from the upper floor to the lower floor in milliseconds. | | DefaultDoorOpenDuration | number | The default time for the elevator to wait with the doors open in milliseconds. | | FloorRange | float | Determines the distance between player and elevator floor to play sounds etc. Minimun value is 3.0, maximum value is 20.0. | | Keybinds | \[key: string]: string; | [Keybinds](https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/) | # Scene Creator Source: https://docs.nonefivem.com/scripts/no-elevators/configuration/scene-creator ## Options *** You can find config file in `no-elevators/config/sh_scene.creator.lua` | Option | type | Description | | ---------- | ----------------------- | ------------------------------------------------------------------------------------------------------------- | | command | string | The command to open the elevator scene creator menu. | | permission | string? | [Access Control Commands](https://docs.fivem.net/docs/server-manual/server-commands/#access-control-commands) | | keybinds | \[key: string]: string; | [Keybinds](https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/) | # Introduction Source: https://docs.nonefivem.com/scripts/no-elevators/index A standalone script delivering a realistic elevator experience. [Tebex Page](https://store.nonefivem.com/packages/6578617). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-elevators` to your server.cfg after no-base. # Elevator Restriction Source: https://docs.nonefivem.com/scripts/no-elevators/restrictions/elevator-restriction An elevator-level restriction disables **all floors** of the elevator if the condition evaluates to `false`. This type of restriction ensures that users are entirely restricted from using the elevator. You can find all of the examples in `no-elevators/restrictions/examples` folder. ### Example *** ```lua theme={null} local API = exports["no-elevators"] local function isAdmin(source) return IsPlayerAceAllowed(source, "elevators.admin") end --In these examples: -- "admin" refers to the elevator ID. -- {"admin", "admin2", "admin3"} applies the restriction to multiple elevators. -- isAdmin serves as the controller function, returning true or false. -- Apply restriction to a single elevator ---@param elevatorIds table | string ---@param controller fun -> boolean API:AddElevatorRestriction("admin", isAdmin) -- Apply restriction to multiple elevators ---@param elevatorIds table | string ---@param controller fun -> boolean API:AddElevatorRestriction({"admin", "admin2", "admin3"}, isAdmin) ``` # Floor Restriction Source: https://docs.nonefivem.com/scripts/no-elevators/restrictions/floor-restriction A **floor-level restriction** limits access to specific floors of an elevator or elevators. If the restriction check returns `false`, the specified floors become inaccessible while others remain accessible. You can find all of the examples in `no-elevators/restrictions/examples` folder. ### Example *** ```lua theme={null} local API = exports["no-elevators"] local function isAdmin(source) return IsPlayerAceAllowed(source, "elevators.admin") end --In this example: -- admin, admin2, admin3, and admin4 are elevator IDs. -- Each floor list (e.g., {1, 2, 3} or 1) defines the restricted floors by their index. -- isAdmin determines whether the user has access. ---@param floors table | number> ---@param controller fun -> boolean API:AddFloorRestriction({ admin = {1, 2, 3}, admin2 = {1, 2, 3}, admin3 = {1, 2, 3}, admin4 = 1 }, isAdmin) ------------------------------------------------------------------------------------------------------------ --In this example: -- "admin2" is the elevator ID. -- 1 or {2, 3, 4} specifies the restricted floors by their index. -- isAdmin determines whether the user has access. ---@param elevatorId string ---@param floors table | number ---@param controller fun -> boolean API:AddFloorRestriction("admin2", 1, isAdmin) API:AddFloorRestriction("admin2", {2, 3, 4}, isAdmin) ``` # Restrictions Source: https://docs.nonefivem.com/scripts/no-elevators/restrictions/index Restrictions are control mechanisms used to determine whether a user has access to the elevator or specific floors within the elevator system. These controls are flexible, stackable, and must return a boolean value (`true` or `false`) to the controller. Depending on the type of restriction applied, access can be restricted at the elevator level or limited to certain floors. **Return Value Requirement:** Restriction must return a boolean value (`true` or `false`). Return `true` for access granted, `false` for access denied. Restriction checks are cached for 5 seconds, ensuring the system doesn't repeatedly evaluate the same conditions. #### Summary of Restriction Logic | Restriction Type | Scope | Behavior | | ------------------------ | ------------------------------- | ------------------------------------------ | | **Elevator Restriction** | Entire elevator system | Disables all floors if `false` is returned | | **Floor Restriction** | Specific floors of the elevator | Disables only the specified floors | # Configuration Source: https://docs.nonefivem.com/scripts/no-gameplaycam/configuration ## Options *** You can find config file in `no-gameplaycam/config/cl_config.lua` | Option | type | Description | | ------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------- | | EnableHelpKeyPrompt | boolean | Enable help key prompt. | | UseHiDof | boolean | Removes blur from zoom. | | EaseDuration | number | Cam swap duration in ms. | | InteriorControl | boolean | Controls is cam in the same interior with player. | | PedControl | boolean | Controls is player visible on the screen. | | MaxDistance | number | Maximum distance between player and camera. | | MaxWarning | number | Maximum warning count (Every sec). | | TransitionSpeed | number\[] | Minimum - maximum transition speed. | | RotateSpeed | number\[] | Minimum - maximum rotation speed. | | ZoomSpeed | number\[] | Minimum - maximum zoom speed. | | MaxRotateAngle | number | Maximum U/D rotation angle (0.0 - 90.0). | | WarningSound | `{Name: string; Ref: string}` | [GTA Sounds](https://gist.github.com/Sainan/021bd2f48f1c68d3eb002caab635b5a4). | | Keys | `[key: string]: string` | Default keys for mapping. | | Controls | `[key: string]: {index: number; label: string}` | [FiveM key controls](https://docs.fivem.net/docs/game-references/controls/#controls). | # Exports & Events Source: https://docs.nonefivem.com/scripts/no-gameplaycam/exports-and-events ## Client Exports Disables cam usage. Enables cam usage. Activates cam. Closes cam. # Introduction Source: https://docs.nonefivem.com/scripts/no-gameplaycam/index FiveM resource for improved gameplay cam. [Tebex Page](https://store.nonefivem.com/packages/6159765). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-gameplaycam` to your server.cfg after no-base. # Configuration Source: https://docs.nonefivem.com/scripts/no-gps-tracker/configuration You can find config file in `no-gps-tracker/config/shared.lua` ## Inventory | Option | Type | Description | | --------------- | ------- | -------------------------------------------------------------- | | Enabled | boolean | Enable or disable the GPS tracker inventory item functionality | | TrackerItemName | string | The name of the GPS tracker item in the inventory system | ## Tracker | Option | Type | Description | | ------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ControllerInterval | number | Interval in milliseconds for how often the tracker controller ticks to record data points. Higher values reduce server load but decrease tracking accuracy. Minimum recommended is 2000 (2 seconds) | | GlobalVehicleScanInterval | number | Interval in milliseconds for how often to scan all vehicles for trackers that are not currently attached. Minimum recommended is 30000 (30 seconds) | | DeleteTrackerIfNoAccess | boolean | Deletes tracker if no one has access to it anymore. Good for cleanup of abandoned trackers | ## Custom Functions ### GetEntityIdentifier Gets entity identifier (plate, VIN, etc). Return `nil` if you don't want this entity to be tracked. ```lua theme={null} ---@param entity number The entity to get the identifier for. ---@return string|nil The identifier for the entity or nil if not found. GetEntityIdentifier = function(entity) -- By default use vehicle plate as identifier -- You should use VIN or other unique identifier if possible return GetVehicleNumberPlateText(entity) end ``` ### GetIsEntityPersistent Checks if entity is persistent (can be found later like player vehicles). This is required for optimized tracker lookups. ```lua theme={null} ---@param entity number The entity to check. ---@param entity_identifier string This matches what GetEntityIdentifier returns. ---@return boolean is_persistent True if the entity is persistent, false otherwise. GetIsEntityPersistent = function(entity, entity_identifier) -- By default it assumes vehicles with NPC style plates are not persistent -- GTA V NPC plates are 8 chars and in format like 12ABC345 unless changed if #entity_identifier == 8 and entity_identifier:match("^%d%d[A-Z][A-Z][A-Z]%d%d%d$") then return false -- Do not persist NPC vehicles end -- You should implement your own logic to determine if the entity is persistent -- Such as is it owned by a player, is it registered in a database, etc. return true -- Assume persistent end ``` For best performance, use fast checks like `Entity(entity).state.is_owned` instead of database queries in `GetIsEntityPersistent`, as this function is called frequently. # Exports & Events Source: https://docs.nonefivem.com/scripts/no-gps-tracker/exports-and-events ## Client Exports Checks if an entity is being tracked (has any trackers attached). **Parameters** * entity: number **Returns** * is\_tracked: boolean **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) local isTracked = exports['no-gps-tracker']:is_entity_being_tracked(vehicle) if isTracked then print("This vehicle has GPS trackers attached!") end ``` Gets all tracker IDs attached to an entity. **Parameters** * entity: number **Returns** * tracker\_ids: `string[]` **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) local trackerIds = exports['no-gps-tracker']:get_entity_trackers(vehicle) for _, trackerId in ipairs(trackerIds) do print("Tracker found: " .. trackerId) end ``` Checks if a specific tracker is attached to an entity. **Parameters** * entity: number * tracker\_id: string **Returns** * is\_attached: boolean **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) local isAttached = exports['no-gps-tracker']:is_tracker_on_entity(vehicle, "tracker_123") if isAttached then print("Tracker tracker_123 is on this vehicle") end ``` Gets the count of trackers attached to an entity. **Parameters** * entity: number **Returns** * count: number **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) local count = exports['no-gps-tracker']:get_entity_tracker_count(vehicle) print("This vehicle has " .. count .. " trackers attached") ``` Checks if the player is currently placing a tracker. **Returns** * is\_placing: boolean **Example** ```lua theme={null} if exports['no-gps-tracker']:is_placing_tracker() then print("Player is currently placing a tracker") end ``` Initiates tracker placement on a targeted vehicle. Finds the vehicle the player is looking at and attempts to place the tracker. **Parameters** * tracker\_id: string **Returns** * success: boolean * error\_message?: string **Example** ```lua theme={null} local success, errorMsg = exports['no-gps-tracker']:find_and_place_tracker("tracker_123") if success then print("Tracker placed successfully!") else print("Failed to place tracker: " .. (errorMsg or "unknown error")) end ``` Places a tracker on a specific entity. **Parameters** * tracker\_id: string * entity: number **Returns** * success: boolean * error\_message?: string **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) local success, errorMsg = exports['no-gps-tracker']:place_tracker("tracker_123", vehicle) if success then print("Tracker placed on vehicle!") else print("Failed: " .. (errorMsg or "unknown error")) end ``` Checks if the player is currently removing a tracker. **Returns** * is\_removing: boolean **Example** ```lua theme={null} if exports['no-gps-tracker']:is_removing_tracker() then print("Player is currently removing a tracker") end ``` Initiates tracker removal from a targeted vehicle. **Returns** * success: boolean * error\_message?: string **Example** ```lua theme={null} local success, errorMsg = exports['no-gps-tracker']:find_and_remove_tracker() if success then print("Tracker removed successfully!") else print("Failed to remove tracker: " .. (errorMsg or "unknown error")) end ``` Removes a tracker from a specific entity. **Parameters** * entity: number **Returns** * success: boolean * error\_message?: string **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) local success, errorMsg = exports['no-gps-tracker']:remove_tracker(vehicle) if success then print("Tracker removed from vehicle!") end ``` Checks if the GPS tracker NUI is currently open. **Returns** * is\_open: boolean **Example** ```lua theme={null} if exports['no-gps-tracker']:is_nui_open() then print("GPS Tracker UI is open") end ``` Opens the GPS tracker NUI. **Example** ```lua theme={null} exports['no-gps-tracker']:open_nui() ``` Closes the GPS tracker NUI. **Example** ```lua theme={null} exports['no-gps-tracker']:close_nui() ``` Toggles the GPS tracker NUI. **Example** ```lua theme={null} exports['no-gps-tracker']:toggle_nui() ``` Gets all nearby vehicles that have trackers attached. **Parameters** * radius?: number (default: 50.0) **Returns** * vehicles: `{entity: number, tracker_ids: string[]}[]` **Example** ```lua theme={null} local trackedVehicles = exports['no-gps-tracker']:get_nearby_tracked_vehicles(100.0) for _, data in ipairs(trackedVehicles) do print("Vehicle " .. data.entity .. " has " .. #data.tracker_ids .. " trackers") end ``` Gets the vehicle the player is currently in, if it has trackers. **Returns** * entity?: number * tracker\_ids?: `string[]` **Example** ```lua theme={null} local vehicle, trackerIds = exports['no-gps-tracker']:get_current_vehicle_trackers() if vehicle and trackerIds then print("Your vehicle has " .. #trackerIds .. " trackers!") end ``` Checks if the player's current vehicle is being tracked. **Returns** * is\_tracked: boolean **Example** ```lua theme={null} if exports['no-gps-tracker']:is_current_vehicle_tracked() then print("Warning: Your vehicle is being tracked!") end ``` ## Server Exports Gets all active trackers in the system. **Returns** * trackers: `{tracker_id: string, attached_entity: number}[]` **Example** ```lua theme={null} local trackers = exports['no-gps-tracker']:get_active_trackers() for _, tracker in ipairs(trackers) do print("Active tracker: " .. tracker.tracker_id) end ``` Gets a specific tracker by ID if it exists. **Parameters** * tracker\_id: string **Returns** * tracker?: `{tracker_id: string, attached_entity: number}` **Example** ```lua theme={null} local tracker = exports['no-gps-tracker']:get_tracker("tracker_123") if tracker then print("Tracker is attached to entity: " .. tracker.attached_entity) end ``` Gets full tracker info from database including routes and points. **Parameters** * tracker\_id: string **Returns** * tracker?: table **Example** ```lua theme={null} local trackerData = exports['no-gps-tracker']:get_tracker_full("tracker_123") if trackerData then print("Tracker has " .. #trackerData.routes .. " routes") end ``` Gets tracker info from database. **Parameters** * tracker\_id: string **Returns** * tracker?: `{id: string, is_placed: boolean, placed_at: string, placed_by: string, placed_entity_identifier: string}` **Example** ```lua theme={null} local info = exports['no-gps-tracker']:get_tracker_info("tracker_123") if info and info.is_placed then print("Tracker placed on: " .. info.placed_entity_identifier) end ``` Creates a tracker in the database. **Parameters** * tracker\_id: string **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:create_tracker("tracker_456") if success then print("Tracker created in database") end ``` Checks if a tracker is currently active. **Parameters** * tracker\_id: string **Returns** * is\_active: boolean **Example** ```lua theme={null} if exports['no-gps-tracker']:is_tracker_active("tracker_123") then print("Tracker is currently active and tracking") end ``` Gets the count of active trackers. **Returns** * count: number **Example** ```lua theme={null} local count = exports['no-gps-tracker']:get_active_tracker_count() print("Total active trackers: " .. count) ``` Creates a tracker and attaches it to an entity. **Parameters** * tracker\_id: string * entity: number * placer\_identifier?: string **Returns** * success: boolean * error\_message?: string **Example** ```lua theme={null} local identifier = BASE:GetIdentifier(source) local vehicle = GetVehiclePedIsIn(GetPlayerPed(source), false) local success, err = exports['no-gps-tracker']:create_and_attach_tracker_to_entity("tracker_123", vehicle, identifier) if success then print("Tracker created and attached!") end ``` Attaches an existing tracker to an entity (without database upsert). **Parameters** * tracker\_id: string * entity: number **Returns** * success: boolean **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(GetPlayerPed(source), false) local success = exports['no-gps-tracker']:attach_tracker_to_entity("tracker_123", vehicle) ``` Checks if an entity is being tracked. **Parameters** * entity: number **Returns** * is\_tracked: boolean **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(GetPlayerPed(source), false) if exports['no-gps-tracker']:is_entity_being_tracked(vehicle) then print("This vehicle is being tracked") end ``` Gets all tracker IDs attached to an entity. **Parameters** * entity: number **Returns** * tracker\_ids: `string[]` **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(GetPlayerPed(source), false) local trackerIds = exports['no-gps-tracker']:get_entity_trackers(vehicle) print("Found " .. #trackerIds .. " trackers on vehicle") ``` Checks if an entity identifier is tracked. **Parameters** * entity\_identifier: string **Returns** * is\_tracked: boolean **Example** ```lua theme={null} local plate = "ABC123" if exports['no-gps-tracker']:is_entity_identifier_tracked(plate) then print("Vehicle with plate " .. plate .. " is being tracked") end ``` Gets all trackers for an entity identifier from database. **Parameters** * entity\_identifier: string **Returns** * trackers: table **Example** ```lua theme={null} local trackers = exports['no-gps-tracker']:get_trackers_by_entity_identifier("ABC123") for _, tracker in ipairs(trackers) do print("Tracker: " .. tracker.id) end ``` Gets all trackers placed by a specific identifier. **Parameters** * identifier: string **Returns** * trackers: table **Example** ```lua theme={null} local identifier = BASE:GetIdentifier(source) local trackers = exports['no-gps-tracker']:get_trackers_by_placer(identifier) print("Player has placed " .. #trackers .. " trackers") ``` Gets the entity identifier for a given entity. **Parameters** * entity: number **Returns** * identifier?: string **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(GetPlayerPed(source), false) local identifier = exports['no-gps-tracker']:get_entity_identifier(vehicle) print("Vehicle identifier: " .. (identifier or "none")) ``` Checks if an entity is persistent. **Parameters** * entity: number **Returns** * is\_persistent: boolean **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(GetPlayerPed(source), false) if exports['no-gps-tracker']:is_entity_persistent(vehicle) then print("This is a persistent vehicle (player-owned)") end ``` Removes all trackers from a given entity. **Parameters** * entity: number **Returns** * removed\_count: number **Example** ```lua theme={null} local vehicle = GetVehiclePedIsIn(GetPlayerPed(source), false) local removed = exports['no-gps-tracker']:remove_trackers_from_entity(vehicle) print("Removed " .. removed .. " trackers from vehicle") ``` Removes a specific tracker by ID. **Parameters** * tracker\_id: string **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:remove_tracker("tracker_123") if success then print("Tracker removed successfully") end ``` Removes all trackers from a given entity by identifier. **Parameters** * entity\_identifier: string **Returns** * removed\_count: number **Example** ```lua theme={null} local removed = exports['no-gps-tracker']:remove_trackers_from_entity_by_identifier("ABC123") print("Removed " .. removed .. " trackers from vehicle with plate ABC123") ``` Deletes a tracker if it has no access entries. **Parameters** * tracker\_id: string **Example** ```lua theme={null} exports['no-gps-tracker']:delete_tracker_if_no_access("tracker_123") ``` Lists trackers accessible by a player. **Parameters** * source: number * page: number * page\_size: number * search?: string **Returns** * result: `{total: number, page: number, page_size: number, hasMore: boolean, trackers: table}` **Example** ```lua theme={null} local result = exports['no-gps-tracker']:list_player_trackers(source, 1, 10) print("Player has access to " .. result.total .. " trackers") for _, tracker in ipairs(result.trackers) do print("- " .. tracker.id) end ``` Lists trackers accessible by an identifier. **Parameters** * identifier: string * page: number * page\_size: number * search?: string **Returns** * result: `{total: number, page: number, page_size: number, hasMore: boolean, trackers: table}` **Example** ```lua theme={null} local identifier = BASE:GetIdentifier(source) local result = exports['no-gps-tracker']:list_player_trackers_by_identifier(identifier, 1, 10) print("Found " .. result.total .. " trackers") ``` Lists routes for a specific tracker. **Parameters** * tracker\_id: string * page: number * page\_size: number **Returns** * result: table **Example** ```lua theme={null} local routes = exports['no-gps-tracker']:list_tracker_routes("tracker_123", 1, 10) for _, route in ipairs(routes) do print("Route from " .. route.started_at) end ``` Grants access to a tracker for a player by source. **Parameters** * tracker\_id: string * source: number * access\_type: string ("view" | "full") **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:grant_tracker_access("tracker_123", targetSource, "view") if success then print("Granted view access to player") end ``` Grants access to a tracker for a specific identifier. **Parameters** * tracker\_id: string * identifier: string * access\_type: string ("view" | "full") **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:grant_tracker_access_by_identifier("tracker_123", "license:abc123", "full") ``` Revokes access to a tracker for a player. **Parameters** * tracker\_id: string * source: number **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:revoke_tracker_access("tracker_123", targetSource) if success then print("Access revoked") end ``` Revokes access to a tracker by identifier. **Parameters** * tracker\_id: string * identifier: string **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:revoke_tracker_access_by_identifier("tracker_123", "license:abc123") ``` Removes access and triggers cleanup event. **Parameters** * tracker\_id: string * source: number **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:remove_tracker_access("tracker_123", source) ``` Removes access by identifier and triggers cleanup event. **Parameters** * tracker\_id: string * identifier: string **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:remove_tracker_access_by_identifier("tracker_123", "license:abc123") ``` Checks if a player has access to a specific tracker. **Parameters** * tracker\_id: string * source: number **Returns** * has\_access: boolean * access\_type?: string ("view" | "full") **Example** ```lua theme={null} local hasAccess, accessType = exports['no-gps-tracker']:has_tracker_access("tracker_123", source) if hasAccess then print("Player has " .. accessType .. " access") end ``` Checks if an identifier has access to a specific tracker. **Parameters** * tracker\_id: string * identifier: string **Returns** * has\_access: boolean * access\_type?: string ("view" | "full") **Example** ```lua theme={null} local hasAccess, accessType = exports['no-gps-tracker']:has_tracker_access_by_identifier("tracker_123", "license:abc123") ``` Gets the access list for a tracker. **Parameters** * tracker\_id: string **Returns** * access\_list: `{identifier: string, access_type: string, granted_at: string}[]` **Example** ```lua theme={null} local accessList = exports['no-gps-tracker']:get_tracker_access_list("tracker_123") for _, access in ipairs(accessList) do print(access.identifier .. " has " .. access.access_type .. " access") end ``` Updates the label of a tracker. **Parameters** * tracker\_id: string * label: string **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:update_tracker_label("tracker_123", "My Car Tracker") if success then print("Label updated") end ``` Upserts a tracker with custom fields. **Parameters** * tracker\_id: string * fields: `{is_placed?: number, placed_at?: string, placed_by?: string, placed_entity_identifier?: string, placed_on_persistent_entity?: number, label?: string}` **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:upsert_tracker("tracker_123", { label = "Updated Tracker", is_placed = 1, placed_at = os.date("%Y-%m-%d %H:%M:%S") }) ``` Adds a tracker item to a player's inventory. **Parameters** * source: number * tracker\_id: string **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:add_tracker_item(source, "tracker_123") if success then print("Tracker item added to inventory") end ``` Removes a tracker item from a player's inventory. **Parameters** * source: number * tracker\_id: string **Returns** * success: boolean **Example** ```lua theme={null} local success = exports['no-gps-tracker']:remove_tracker_item(source, "tracker_123") if success then print("Tracker item removed from inventory") end ``` Checks if inventory integration is enabled. **Returns** * is\_enabled: boolean **Example** ```lua theme={null} if exports['no-gps-tracker']:is_inventory_enabled() then print("Inventory integration is enabled") end ``` # Introduction Source: https://docs.nonefivem.com/scripts/no-gps-tracker/index FiveM resource for tracking vehicles with GPS. [Tebex Page](https://store.nonefivem.com/packages/no-gps-tracker). ### Installation 1. Make sure you've installed [no-base](https://docs.nonefivem.com/no-base/#installation) correctly. 2. Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). 3. Drag & drop your resource to `resources/[none]` 4. Add `ensure no-gps-tracker` to your server.cfg after no-base. 5. Make sure to update `GetEntityIdentifier` and `IsEntityPersistent` functions from `no-gps-tracker/config/shared.lua` for better compatiblity. # Access Sharing Source: https://docs.nonefivem.com/scripts/no-housing/access-sharing House owners can share access with other players. ## Features * Share keys with other players * Set permission levels * Manage access through the in-game menu # Adding Building Interaction Source: https://docs.nonefivem.com/scripts/no-housing/configuration/buildings/adding-building-interaction ## What is building interactions? *** Building interactions is functions that adds unique interactions to the building. These interactions can be anything you want. Building interactions are enabled when the player enters the building and disabled when the player leaves the building. For this reason, a function should be returned that will deactive the interaction. To be able to add interaction to the building, you need to add interactions to the building data. ## Examples *** > `no-housing/config/shared/buildings/ipl/meth.lua` ```lua theme={null} local Interactions = { function(building, ctx) local stashCoords = {vector3(970.4816, -146.893, -49.0)} local zoneId = "housing:stash:static" local zones = {} for k, coords in pairs(stashCoords) do zones[#zones + 1] = CreateSphereZone(zoneId, { id = zoneId .. ":" .. k, coords = coords, radius = 1.5, data = k }) end local destroyListener = UsePolyHook(zoneId, { label = "Stash", icon = "box", onPressed = function(stashId, stop) local stash = "housing:static:stash:" .. ctx.id .. ":" .. stashId TriggerEvent("inventory:open", stash, ctx.address) end }) return function() destroyListener() for _, destroy in pairs(zones) do destroy() end end end } Config.Buildings.Ipl.meth = { interactions = Interactions, coords = vector3(978.6258, -144.1735, -48.99), doors = { {coords = vector3(969.4758, -147.1619, -46.40), h = 271.15} }, onEnter = function(ctx) end, onExit = function() end } ``` # Adding IPL Building Source: https://docs.nonefivem.com/scripts/no-housing/configuration/buildings/adding-ipl-building ## Types *** ### Door
FieldTypeDescriptionRequired
coordsvector3coordstrue
hnumberheadingtrue
### Ipl Building
FieldTypeDescriptionRequired
coordsvector3Ipl coordstrue
doorsdoor\[]Inside door coordstrue
realestateReal Estate DataThe data required to be listed in the real estate menufalse
interactionsfunction\[]Building interactionsfalse
radiusnumberFurniture Editor radius based on coords (default 20)false
onEnterfunctionFunction to be executed after the player enters the buildingfalse
onExitfunctionFunction to be executed after the player exits the buildingfalse
## Examples *** > Create `building_name.lua` inside `no-housing/config/shared/buildings/ipl` ```lua theme={null} Config.Buildings.Ipl.building_name = { coords = vector3(1093.6, -3196.6, -38.99) -- building coords, doors = { -- building doors {coords = vector3(1088.674, -3187.672, -38.99), h = 176.64}, {coords = vector3(1103.377, -3195.934, -38.99), h = 91.46} }, realestate = { label = "Building Label", price = 13000 }, onEnter = function(ctx) end, onExit = function() end } ``` # Adding Shell Building Source: https://docs.nonefivem.com/scripts/no-housing/configuration/buildings/adding-shell-building ## Types *** ### Door
FieldTypeDescriptionRequired
coordsvector3coordstrue
hnumberheadingtrue
### Shell Building
FieldTypeDescriptionRequired
shellnumberShell modeltrue
doorsdoor\[]Inside door offsetstrue
coordsvector3Static shell coordsfalse
realestateReal Estate DataThe data required to be listed in the real estate menufalse
interactionsfunction\[]Building interactionsfalse
radiusnumberFurniture Editor radius based on coords (default 20)false
onEnterfunctionFunction to be executed after the player enters the buildingfalse
onExitfunctionFunction to be executed after the player exits the buildingfalse
## Examples *** > Create `building_name.lua` inside `no-housing/config/shared/buildings/shell` ```lua theme={null} Config.Buildings.Shell.building_name = { shell = `shell_model`, -- model of the shell radius = 20.0, -- furniture radius coords = vector3(0.0, 0.0, 0.0), doors = { -- inside door offsets {coords = vector3(-1.4218, -1.9719, 2.9), h = 1.95} }, realestate = { label = "Trailer", price = 15000 }, onEnter = function(ctx) end, onExit = function() end } ``` # Buildings Source: https://docs.nonefivem.com/scripts/no-housing/configuration/buildings/index * [Adding IPL Building](./adding-ipl-building.md): From this section, you can learn how to add ipl buildings * [Adding Shell Building](./adding-shell-building.md): From this section, you can learn how to add shell buildings * [Adding Building Interaction](./adding-building-interaction.md): From this section, you can learn how to add building interactions # Commands Source: https://docs.nonefivem.com/scripts/no-housing/configuration/commands Default commands can be found in `no-housing/config/client/commands.lua`. You can change or completely remove these commands. ### Default ```lua theme={null} RegisterCommand("furniture", function() TriggerEvent("no-housing:furniture:ui") end) RegisterCommand("realestate", function() TriggerEvent("no-housing:realestate:show") end) RegisterCommand("create", function() TriggerEvent("no-housing:housemanager:create") end) RegisterCommand("edit", function() TriggerEvent("no-housing:housemanager:edit") end) ``` # Furniture Interactions Source: https://docs.nonefivem.com/scripts/no-housing/configuration/furniture-interactions In order to use furniture interactions you need to [configure interact](/no-base/configuration/interact-target). You can add interactions based on furniture models or tags. ## Types *** ### Interaction
FieldTypeDescriptionRequired
idstringUnique id for the interactiontrue
labelstringInteraction label to showtrue
onInteractfunctionFunction to execute on interacttrue
tagsstring\[]Furniture tagsfalse
modelsnumber\[]Furniture modelsfalse
iconstringFont Awesome iconfalse
accessRequiredbooleanControls whether the player has access to the house for interact. Default: truefalse
## Examples *** ```lua theme={null} Config.FurnitureInteractions = { { id = "stash", tags = {"stash"}, label = "Stash", icon = "box", onInteract = function(entity, furnitureId, houseId) local stash = "housing:furniture:stash:" .. houseId .. ":" .. furnitureId -- OPEN STASH TriggerEvent("inventory:open", stash) end }, { id = "clothing", tags = {"clothing"}, label = "Clothes", icon = "shirt", accessRequired = false, onInteract = function(entity, furnitureId, houseId) TriggerEvent("clothing:open") end } } ``` # Garage Source: https://docs.nonefivem.com/scripts/no-housing/configuration/garage ## Examples *** ```lua theme={null} Config.Garage = { Open = function(address, spawnPoint) TriggerEvent("garage:open", address, spawnPoint.coords, spawnPoint.h) end, OnEnter = function(address, spawnPoint) TriggerEvent("garage:setCurrent", { name = address, spawnpoints = {spawnPoint} }) end, OnExit = function(address, spawnPoint) TriggerEvent("garage:setCurrent", nil) end } ``` If defined, it will be executed when the player enters the garage zone and press E. ### Parameters * address: string * spawnPoint: `{coords: vector3, h: number}` If defined, it will be executed when the player enters the garage zone. ### Parameters * address: string * spawnPoint: `{coords: vector3, h: number}` If defined, it will be executed when the player exits the garage zone. ### Parameters * address: string * spawnPoint: `{coords: vector3, h: number}` # Real Estate Source: https://docs.nonefivem.com/scripts/no-housing/configuration/real-estate The number of doors and garages in the house effects the price of the house. You can change this prices from `no-housing/config/server/realestate.lua` To be able to list buildings in the real estate menu, you need to [add real estate data to the building](/no-housing/configuration/buildings/adding-shell-building#types). ## Types *** ### Realestate
FieldTypeDescriptionRequired
labelstringBuildings label for real estate menutrue
pricenumberBuildings base pricetrue
# Exports & Events Source: https://docs.nonefivem.com/scripts/no-housing/exports-and-events ## Client Exports ```lua theme={null} -- Get player's houses exports['no-housing']:GetPlayerHouses() -- Enter house exports['no-housing']:EnterHouse(houseId) ``` ## Server Exports ```lua theme={null} -- Get house data exports['no-housing']:GetHouseData(houseId) -- Set house owner exports['no-housing']:SetHouseOwner(houseId, identifier) ``` # Editing Furniture Categories Source: https://docs.nonefivem.com/scripts/no-housing/furniture-editor/editing-furniture-categories > You can edit furniture categories from `no-housing/data/categories.json` You can add as many categories as you want. ## Types *** ### Category | Field | Type | Description | | ----- | ------ | ------------------------- | | id | number | Unique id of the category | | label | string | Label of the category | | icon | string | Font awesome icon name | # Editing Furnitures Source: https://docs.nonefivem.com/scripts/no-housing/furniture-editor/editing-furnitures > You can edit furnitures from `no-housing/data/furnitures.json` When adding new furniture, make sure there are no duplicate models. ## Types *** ## Furniture | Field | Type | Description | | ----------- | --------- | ---------------------------------------------------------------------------------------------- | | name | string | Name of the model | | categoryId | number | Id of the category | | price | number | Price of the furniture | | description | string | | | tags | string\[] | You can use these tags to [add interactions](/no-housing/configuration/furniture-interactions) | # Furniture Editor Source: https://docs.nonefivem.com/scripts/no-housing/furniture-editor/index ## What is furniture editor? *** Furniture editor is used for add/remove furnitures to house. ## Database *** Furnitures are saved in the housing\_furnitures table in the database. | name | description | | --------- | -------------------------------------------------------------------------------------------------- | | id | Unique id of the furniture | | house\_id | Id of the house | | model | Model of the furniture | | offset | Position of the furniture. This will be offset for shell buildings, coordinates for ipl buildings. | | rotation | Rotation of furniture | # House Editor Source: https://docs.nonefivem.com/scripts/no-housing/house-editor The house editor allows you to create and manage houses in-game. ## Usage Use the command `/houseeditor` to open the house editor interface. ## Database House data is stored in the database. You can manage houses directly through the database if needed. # Introduction Source: https://docs.nonefivem.com/scripts/no-housing/index FiveM resource for housing. [Tebex Page](https://nonefivem.tebex.io/). This resource requires [supported framework](/no-base/supported-resources#framework) or configured [player management](/no-base/configuration/player-management). This resource is using [K4MB1's starter shells](https://forum.cfx.re/t/free-props-starter-shells-for-housing-scripts/4826922) by default. You can download and use these shells or remove these shells by deleting the `no-housing/config/shared/buildings/shell/K4MB1startshells` folder and update your house builds from [database](/no-housing/house-editor#database). This resource is using [bob74 ipl](https://github.com/Bob74/bob74_ipl) for ipl buildings. ### Features *** * [Real Estate](/no-housing/configuration/real-estate) * [House Editor](/no-housing/house-editor) * [Furniture Editor](/no-housing/furniture-editor) * Customizable [Buildings](/no-housing/configuration/buildings) & Furnitures * [Furniture Interactions](/no-housing/configuration/furniture-interactions) * [Building Interactions](/no-housing/configuration/buildings/adding-building-interaction) * [Garages](/no-housing/configuration/garage) * [Access Sharing](/no-housing/access-sharing) * Lock Management * IPL & Shell Support * 300+ Houses with different interiors * 400+ Furnitures with images ### Installation *** * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-housing` to your server.cfg after no-base. # Configuration Source: https://docs.nonefivem.com/scripts/no-lapdance/configuration ## Options *** You can find config file in `no-lapdance/config/sh_config.lua` | Option | type | Description | | ----------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | command | string \| undefined | Command for players to create lapdance scene. | | scene\_render\_distance | number | Distance between player and dancer to create the scene. | | dance\_price | number | The default dance price. | | enable\_zones\_for\_all | boolean | Creates interaction zone for chairs even if they have target option. | | icons | `[key: string]: string;` | [Icons](https://fontawesome.com/v6/search?m=free) | | keybinds | `{dancer: [key: string]: string; male: [key: string]: string; scene_creator: [key: string]: string}` | [Keybinds](https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/) | # Introduction Source: https://docs.nonefivem.com/scripts/no-lapdance/index A standalone script delivering a realistic elevator experience. [Tebex Page](https://store.nonefivem.com/packages/6908949). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-lapdance` to your server.cfg after no-base. # Client Source: https://docs.nonefivem.com/scripts/no-mop/configuration/client ## Options *** | Field | Type | Description | | --------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- | | MaxDirtPoint | number | Maximum dirt points that can be collected. | | DirtPointAdjustment | number | Point adjustment while standing on the dirty surface. (Every 1 sec) | | DirtPointDecreaseMultiplier | number | Multiplies DirtPointAdjustment and removes from the dirt point while standing on the clean surface. (Every 1 sec) | | RequiredDirtPoint | number | Required point to leave dirt behind. | | DisabledInteriors | number\[] | [How to disable interiors?](/no-mop/configuration/how-to-disable-pollution-for-interiors) | | CustomWalkStyles | string\[] | In order to reset player's walking style you need to add your custom walking styles here. | # How to disable pollution for interiors? Source: https://docs.nonefivem.com/scripts/no-mop/configuration/how-to-disable-pollution-for-interiors You can simply add interior's hash to `Config.Dirt.DisabledInteriors` in `no-mop/config/client/cl_config.lua` ## Example *** ```lua theme={null} Config.Dirt = { -- Disabled interior hashes DisabledInteriors = { 4109159231, 160563028 } } ``` ## How to get interior's hash? *** You can run `GetInteriorFromEntity(PlayerPedId())` on the client while inside the interior. Or you can enable debug mode by adding `debug_enable "*"` to `no-mop/fxmanifest.lua` and get the hash from the interior's id. # Configuration Source: https://docs.nonefivem.com/scripts/no-mop/configuration/index ## Options *** You can find config file in `no-mop/config/shared.lua` | Option | type | Description | | ----------------------- | ---------------------- | --------------------------------------- | | ItemName | string | Mop item | | IndicatorTimeout | number | Removes indicators after x milliseconds | | MaxDirtCountForInterior | number | Maximum dirt count for per interior. | | DirtTimeout | number | Fade outs dirt in x minutes | | Keys | \[key: string]: string | Default keys for mapping | # Use with commands Source: https://docs.nonefivem.com/scripts/no-mop/configuration/use-with-commands You can find the commands in `no-mop/config/client/cl_commands.lua`. You can uncomment the lines to use with commands. # Exports & Events Source: https://docs.nonefivem.com/scripts/no-mop/exports-and-events ## Client Net Events Toggles the mop. Equips the mop. Removes the mop. # Introduction Source: https://docs.nonefivem.com/scripts/no-mop/index FiveM resource for mop. [Tebex Page](https://store.nonefivem.com/packages/6050361). ## Features *** * Synchronized animations, cam, props & particles. * Interiors getting dirty. * Depends on where the player walked before, their steps will leave dirt behind. * Works on every interior. * You can disable this option for certain interiors. * Sync with other players. ## Installation *** * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-mop` to your server.cfg after no-base. # Configuration Source: https://docs.nonefivem.com/scripts/no-newspaper/configuration/index ## Options *** You can find config file in `no-newspaper/config/sh_config.lua` | Option | type | Description | | ---------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------ | | ItemName | string | Newspaper item | | IndicatorTimeout | string? | Removes indicators after x milliseconds | | Keys | \[key: string]: string | Default keys for mapping | | Icons | \[key: string]: string | Fontawesome icons that are used in menus and interactions (target) | | EditorZones | \[key: string]: vector3 | Adds menu interaction (target) to given coords. See [Registering Papers](/no-newspaper/exports-and-events#registerpaper) | # Registering Papers Source: https://docs.nonefivem.com/scripts/no-newspaper/configuration/registering-papers ## Types *** #### PaperContext | Field | Type | Description | | ----------- | --------------------------------- | ------------------------------------------------------------------------------ | | id | string | Unique id of the paper | | label | string | Label of the paper | | price | number? | Price of the paper | | icon | string? | [Fontawesome icon](https://fontawesome.com/icons) to use in menus. | | canPublish | function(source: number): boolean | Function that determines is player allowed to publish article from this paper. | | canDelete | function(source: number): boolean | Function that determines is player allowed to delete article from this paper. | | onPurchased | function(source: number)? | Function that executes when someone purchased a newspaper from this paper. | ## How to Register Paper? *** You can register paper using API.RegisterPaper. You can find default WeazelNews paper in `no-newspaper/newspapers/sh_weazelnews.lua` You can copy this file and edit variables to create a new paper or you can register paper from another resource using API. API examples can be found in `no-newspaper/api/server/examples.lua` ## Examples *** ```lua theme={null} local API = exports["no-newspaper"] local WeazelNews = API:RegisterPaper({ id = "weazelnews", label = "Weazel News", canPublish = function(source) local player = ESX.GetPlayerFromId(source) return player and player.job.name == "weazelnews" end, canDelete = function(source) local player = ESX.GetPlayerFromId(source) return player and player.job.name == "weazelnews" end }) local function PrintArticles(articles) for _, article in pairs(articles) do print(article.id) print(article.header) print(article.author) print(article.content) print(article.image) print(article.date) end end local function PrintAllArticles() local articles = WeazelNews:GetAllArticles() PrintArticles(articles) end local function PrintArticlesByDate(date) local articles = WeazelNews:GetArticles(date) PrintArticles(articles) end RegisterNetEvent("jail:player", function(source, months) local player = ESX.GetPlayerFromId(source) if not player then return end local fullname = player.get("firstname") .. " " .. player.get("lastname") WeazelNews:Publish({ header = "Jail Sentence", author = "Bolingbroke Penitentiary", content = fullname .. " sentenced for " .. months .. " months in jail!" }) end) ``` # Exports & Events Source: https://docs.nonefivem.com/scripts/no-newspaper/exports-and-events ## Server Exports Registers newspaper. **Parameters** * context: [PaperContext](/no-newspaper/configuration/registering-papers#papercontext) Publishes article on given paper id. **Parameters** * paperId: number * context: Article Context Publishes article in all papers. **Parameters** * context: Article Context Returns articles by date on given paper id. **Parameters** * paperId: number **Returns** * articles: Article Context\[] Returns all articles on given paper id. **Parameters** * paperId: number **Returns** * articles: Article Context\[] # Introduction Source: https://docs.nonefivem.com/scripts/no-newspaper/index FiveM resource for newspaper. [Tebex Page](https://store.nonefivem.com/packages/6030899). This resource requires [supported interact (target) resource](/no-base/supported-resources#interact-target) or [configuration](/no-base/configuration/interact-target). ## Features *** * DUI for newspaper. * Create & manage multiple newspapers. * You can create as many newspapers as you want. * You can specify who has permissions for actions. * See [registering papers](/no-newspaper/configuration/registering-papers). * Article editor. * Newspaper camera. * Newspaper aging. * Newspaper start to wear out after 3 days. * Aging is reflected visually. * Animations & props. * Newspaper item. * Newspapers are kept in inventory as items. Articles are displayed according to the date of purchase and the newspaper company. * API with examples. * See [exports](/no-newspaper/exports-and-events). Examples of how to use them are included with purchase. * Sync with other players. ## Installation *** * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-newspaper` to your server.cfg after no-base. # Configuration Source: https://docs.nonefivem.com/scripts/no-payphone/configuration ## Options *** You can find config file in `no-payphone/config/sh_config.lua` | Option | type | Description | | -------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------- | | ShowCaller | boolean | If true payphone will display the caller's number | | CallTimeout | number | Ends call if no one answers in x milliseconds. | | PayphoneModels | number\[] | Player's can use these models as payphone. Note: Models will be replaced by p\_phonebox\_01b\_s while payphone being used. | | Keys | \[key: string]: string | Default keys for mapping | # Introduction Source: https://docs.nonefivem.com/scripts/no-payphone/index FiveM resource for payphone. [Tebex Page](https://store.nonefivem.com/packages/6066790). This resource requires [supported interact (target) resource](/no-base/supported-resources#interact-target) or [configuration](/no-base/configuration/interact-target). ## Features *** * Synchronized animations, props & sounds. * Payphones has their own unique number. * Players can use payphones for calling or get calls from payphones. ## Installation *** * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-payphone` to your server.cfg after no-base. # Integration Source: https://docs.nonefivem.com/scripts/no-payphone/integration/index You can find integration files in `no-payphone/config/integration` * [VOIP Integration](./voip-integration) * [Phone Integration](./phone-integration) # Phone Integration Source: https://docs.nonefivem.com/scripts/no-payphone/integration/phone-integration You can find phone implementations in `no-payphone/integration/phone` Phone integration can be a little more complicated. To do this we need to add event listeners for payphone events and trigger phone events. ## Ready Integrations *** * [qb-phone](https://github.com/qbcore-framework/qb-phone) ## Payphone Events *** This events will be triggered by payphone. Triggered when payphone starts the call. ### Parameters * ctx: `{source: number; number: string; targetNumber: string; callId: number}` ctx.source is the caller's server id. ctx.number is payphone's number. ctx.targetNumber is the number payphone is calling. ctx.callId is the call Id generated from payphone. (You don't need to use this) Triggered when payphone answers the call. ### Parameters * ctx: `{source: number; number: string; targetNumber: string; callId: number}` ctx.source is the caller's server id. ctx.number is payphone's number. ctx.targetNumber is the number payphone is calling. ctx.callId is the call Id generated from payphone. (You don't need to use this) Triggered when payphone ends the call. ### Parameters * ctx: `{number: string; targetNumber: string}` ctx.number is payphone's number. ctx.targetNumber is the number payphone is calling. ## Phone Events *** This events expected to triggered by phone. Triggered when phone starts the call. ### Parameters * ctx: `{source: number; number: string; targetNumber: string; callId?: number}` ctx.source is the caller's server id. ctx.number is the phone's number. ctx.targetNumber is the number phone is calling. ctx.callId: Generated call id (If nil payphone will generate itself.). Triggered when phone answers the call. ### Parameters * ctx: `{source: number; number: number}` ctx.source is the caller's server id. ctx.number is the phone's number. Triggered when phone ends the call. ### Parameters * phoneNumber: string ## Example *** This is an example for qb-phone. You can find this integration in `no-payphone/config/integration/phone/qb-phone.lua` ```lua theme={null} if not _IS_SERVER or not HasResource("qb-phone") then return end -- NOTES --- IN ORDER TO LET PLAYERS CALL NON-PLAYER NUMBERS YOU NEED TO CHANGE CALLBACK CALLED "qb-phone:server:GetCallState" IN qb-phone/server/main.lua:163 WITH THIS -- cb(true, true) EVEN IF TARGET IS NIL -- QBCore.Functions.CreateCallback('qb-phone:server:GetCallState', function(_, cb, ContactData) -- local Target = QBCore.Functions.GetPlayerByPhone(ContactData.number) -- if Target ~= nil then -- if Calls[Target.PlayerData.citizenid] ~= nil then -- if Calls[Target.PlayerData.citizenid].inCall then -- cb(false, true) -- else -- cb(true, true) -- end -- else -- cb(true, true) -- end -- else -- cb(true, true) -- end -- end) -- SERVER START local QBCore = exports["qb-core"]:GetCoreObject() -- payphone start the call ---@param ctx table ---@field source number ---@field number string ---@field targetNumber string ---@field callId number AddEventHandler("no-payphone:call:start", function(ctx) local target = QBCore.Functions.GetPlayerByPhone(ctx.targetNumber) if not target then return end TriggerClientEvent("qb-phone:client:GetCalled", target.PlayerData.source, ctx.number, ctx.callId, false) end) -- payphone answer the call ---@param ctx table ---@field source number ---@field number string ---@field targetNumber string ---@field callId number AddEventHandler("no-payphone:call:answer", function(ctx) local target = QBCore.Functions.GetPlayerByPhone(ctx.targetNumber) if not target then return end TriggerClientEvent("qb-phone:client:AnswerCall", target.PlayerData.source) end) -- payphone end the call ---@param ctx table ---@field number string ---@field targetNumber string AddEventHandler("no-payphone:call:end", function(ctx) local target = QBCore.Functions.GetPlayerByPhone(ctx.targetNumber) if not target then return end TriggerClientEvent("qb-phone:client:CancelCall", target.PlayerData.source) end) -- phone start the call RegisterNetEvent("qb-phone:server:CallContact", function(targetData, callId) local player = QBCore.Functions.GetPlayer(source) if not player then return end TriggerEvent("no-payphone:phone:start", { source = source, -- number number = player.PlayerData.charinfo.phone, -- string targetNumber = targetData.number, -- string callId = callId -- number? }) end) -- phone answer the call RegisterNetEvent("qb-phone:server:AnswerCall", function(ctx) local player = QBCore.Functions.GetPlayer(source) if not player then return end TriggerEvent("no-payphone:phone:answer", { source = source, -- number number = player.PlayerData.charinfo.phone }) end) -- phone cancel the call RegisterNetEvent("qb-phone:server:CancelCall", function(ctx) local player = QBCore.Functions.GetPlayer(source) if not player then return end TriggerEvent("no-payphone:phone:end", player.PlayerData.charinfo.phone) end) ``` # VOIP Integration Source: https://docs.nonefivem.com/scripts/no-payphone/integration/voip-integration You can find voip integrations in `no-payphone/integration/voip` Voip integration is simple. You only need to add 2 functions, one of them adds the player to the call and the other one removes the player from the call. ## Ready Integrations *** * [pma-voice](https://github.com/AvarianKnight/pma-voice) * [mumble-voip](https://github.com/FrazzIe/mumble-voip-fivem) * [toko-voip](https://github.com/Itokoyamato/TokoVOIP_TS3) ## Example *** This is an example for pma-voice. You can find this integration in `no-payphone/config/integration/voip/pma-voice.lua` ```lua theme={null} if _IS_SERVER or not HasResource("pma-voice") then return end -- CLIENT START local PMA_VOICE = exports["pma-voice"] ---@param callId number Config.Voip.AddPlayerToCall = function(callId) return PMA_VOICE:addPlayerToCall(callId) end ---@param callId number Config.Voip.RemovePlayerFromCall = function(callId) return PMA_VOICE:removePlayerFromCall() end ``` # Configuration Source: https://docs.nonefivem.com/scripts/no-polaroid/configuration You can find config file in `no-polaroid/config/shared.lua`. ## Media Upload *** Images are uploaded using the media upload system configured in no-base. See the [Media Upload documentation](/scripts/no-base/configuration/media-upload) for available providers and configuration options. ## Date Locale *** You can specify date locale for polaroid dates. [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). ## Keys *** You can set default keys for mapping from Config.Keys. ## Filters *** You can add & remove filters from Config.Filters. [Filter List](https://wiki.rage.mp/index.php?title=Timecycle_Modifiers). ## Adding As Item *** If you are using [supported inventory](/no-base/supported-resources#inventory) you can set item names from Config.Items or check for use [events](/no-polaroid/exports-and-events#client-net-events). # Exports & Events Source: https://docs.nonefivem.com/scripts/no-polaroid/exports-and-events ## Client Net Events Toggles camera. Opens camera. Closes camera. Toggles polaroid photo. **Parameters** * ctx: `{image: string, date?: number}` Shows polaroid photo. **Parameters** * ctx: `{image: string, date?: number}` Closes polaroid photo. This event will be triggered by us when the photo is ready. You can change normal behavior by listening this event. **Parameters** * ctx: `{image: string; date: number}` ## Server Net Events This event will be triggered by us when the photo is ready. You can change normal behavior by listening this event. **Parameters** * ctx: `{image: string; date: number}` # Introduction Source: https://docs.nonefivem.com/scripts/no-polaroid/index FiveM resource for polaroid photos. [Tebex Page](https://store.nonefivem.com/packages/5971063). ### Features *** * Animations & props * Customizable filters * Filter strength option * DUI for photos * Save photos as item * Sync with other players ### Installation *** * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-polaroid` to your server cfg after no-base. # Configuration Source: https://docs.nonefivem.com/scripts/no-rappel/configuration ## Options *** You can find config file in `no-rappel/config/sh_config.lua` | Option | type | Description | | -------------------- | ------- | ----------------------------------------------------------- | | MaxRopeLength | number | Maximum length of rope | | MinRopeLength | number | Minimum length of rope | | MinOffset | number | Minimum distance between player and start coords. | | MaxOffset | number | Maximum distance between player and start coords. | | EnableIndicators | boolean | Whether to indicators will be showed when start rappelling. | | IndicatorTimeout | number | Removes indicators after x milliseconds | | Command | string? | Rappel command | | ItemName | string? | Name of the item | | RemoveItemAfterUsage | boolean | Whether to removes the item on start rappeling. | # Exports & Events Source: https://docs.nonefivem.com/scripts/no-rappel/exports-and-events ## Client Net Events Toggles rappelling. Toggles rappelling. Starts rappelling, if available. Stops rappelling. # Introduction Source: https://docs.nonefivem.com/scripts/no-rappel/index FiveM resource for rappelling. [Tebex Page](https://store.nonefivem.com/packages/5993963). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-rappel` to your server.cfg after no-base. # Client Source: https://docs.nonefivem.com/scripts/no-spy/configuration/client You can find client config file in `no-spy/config/client/cl_config.lua` ## Enable Access Menu *** Enables buttons for access management. ## Pickup Mode *** | Option | Description | | -------- | ---------------------------------------------- | | access | Only people with access can pick up the device | | everyone | Everyone can pick up the device | ## Enable Shoot To Destroy *** If enabled, players can shoot the cams or motion sensors to destroy them. ## Spy Cam *** | Field | Type | Description | | ------------- | ------- | -------------------------------------------------------- | | PlayAnimation | boolean | Whether to play the animation while checking cams or not | ## Motion Sensor *** | Field | Type | Description | | -------------- | ----------------------------------------- | --------------------------------------- | | DetectionRange | number | The distance the device will detect | | PlaySound | boolean | Whether to play a sound when notified | | Notification | function(label: string, location: string) | Overrides default notification behavior | ## Keys *** Default keys for mapping. ## Filters *** The filter used when using the device. You can change or remove the filters completely. # Commands Source: https://docs.nonefivem.com/scripts/no-spy/configuration/commands You can find commands in `no-polaroid/config/client/commands.lua`. You can change or completely remove these commands. ## Default Commands *** ```lua theme={null} RegisterCommand("cams", function() TriggerEvent("no-spy:devicemanager:menu", "cam") end) RegisterCommand("sensors", function() TriggerEvent("no-spy:devicemanager:menu", "motionsensor") end) RegisterCommand("devices", function() TriggerEvent("no-spy:devicemanager:menu") end) ``` # Configuration Source: https://docs.nonefivem.com/scripts/no-spy/configuration/index You can find config file in `no-spy/config/shared/sh_config.lua` ## Media Upload *** Images are uploaded using the media upload system configured in no-base. See the [Media Upload documentation](/scripts/no-base/configuration/media-upload) for available providers and configuration options. ## Date Locale *** You can specify date locale for photo dates. [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). ## Lua Date Format *** You can specify date format for device menu.[ Lua Date](https://www.lua.org/pil/22.1.html). ## Adding As Item *** If you are using [supported inventory](/no-base/supported-resources#inventory) you can set item names from Config.Items or check for use [events](/no-spy/exports-and-events). # Exports & Events Source: https://docs.nonefivem.com/scripts/no-spy/exports-and-events ## Client Exports *** #### GetDeviceList Returns device list. **Returns** * list: `{id: number; label: string; type: string; coords: vector3; location: string; date: string}` *** #### GetDeviceId Returns device id from entity. **Parameters** * entity: number **Returns** * deviceId?: number *** #### HasDevice Returns has access to given device id. **Parameters** * deviceId: number **Returns** * hasAccess: boolean *** #### AddInteraction Adds interaction to the devices. **Parameters** * ctx: `{id: string; devices: string[]; label: string; icon: string; accessRequired?: boolean; onInteract: function(entity, deviceId); isEnabled: function(entity, deviceId);}` *** ## Server Exports *** #### GetDeviceList Returns device list. **Parameters** * source: number **Returns** * list: `{id: number; label: string; type: string; owned: boolean; coords: vector3; netId: number; date: string}` *** #### GetDeviceListByUserId Returns device list. **Parameters** * userId: number **Returns** * list: `{id: number; label: string; type: string; owned: boolean; coords: vector3; netId: number; date: string}` *** #### AccessGive Grants device access to the given source. **Parameters** * deviceId: number * source: number **Returns** * success: boolean *** #### AccessGiveByUserId Grants device access to the given userId. **Parameters** * deviceId: number * userId: number **Returns** * success: boolean *** #### AccessRemove Removes device access from the given source. **Parameters** * deviceId: number * source: number **Returns** * success: boolean *** #### AccessRemoveByUserId Removes device access from the given userId. **Parameters** * deviceId: number * userId: number **Returns** * success: boolean *** #### AccessReset Resets device accesses. **Parameters** * deviceId: number **Returns** * success: boolean *** #### AccessShare Shares access with given target if player has access. **Parameters** * deviceId: number * source: number * targetSource: number **Returns** * success: boolean *** #### Destroy Removes device entirely. **Parameters** * deviceId: number **Returns** * success: boolean *** ## Client Net Events *** #### no-spy:close Turns off all devices. *** #### no-spy:devicemanager:menu Opens the devices menu. **Parameters** * type?: cam | motionsensor *** #### no-spy:glasses:use Toggles spy glasses. *** #### no-spy:glasses:putOn Puts on glasses. *** #### no-spy:glasses:remove Removes glasses. *** #### no-spy:glasses:activate Activates glasses if equipped. *** #### no-spy:glasses:deactivate Deactivates glasses. *** #### no-spy:cam:use Starts cam placement. *** #### no-spy:cam:connect Connects to cam. **Parameters** * deviceId: number *** #### no-spy:cam:disconnect Disconnects from cam. *** #### no-spy:motionsensor:use Starts motion sensor placement. *** #### no-spy:motionsensor:notify Sends sensor notification. **Parameters** * deviceLabel: string *** #### no-spy:photo:use Toggles photo. **Parameters** * ctx: `{image: string, date?: number}` *** #### no-spy:photo:show Shows photo. **Parameters** * ctx: `{image: string, date?: number}` *** #### no-spy:photo:close Closes photo. *** #### no-spy:photo:ready This event will be triggered by us when the photo is ready. You can change normal behavior by listening this event. **Parameters** * ctx: `{image: string; date: number}` *** ## Server Net Events *** #### no-spy:photo:ready This event will be triggered by us when the photo is ready. You can change normal behavior by listening this event. **Parameters** * ctx: `{image: string; date: number}` *** #### no-spy:cam:place Places cam. **Parameters** * deviceCtx: `{label: string}` * placementCtx: `{coords: vector3; rotation: vector3}` *** #### no-spy:motionsensor:notify Sends sensor notification to device owners. **Parameters** * deviceId: number *** #### no-spy:motionsensor:place Places motion sensor. **Parameters** * deviceCtx: `{label: string}` * placementCtx: `{coords: vector3; rotation: vector3}` # Introduction Source: https://docs.nonefivem.com/scripts/no-spy/index FiveM resource for spy items. [Tebex Page](https://store.nonefivem.com/packages/5981044). This resource requires [supported interact (target) resource](/no-base/configuration/interact-target), configured [player controls and actions](/no-base/configuration/player-management). ### Features *** * Spy cam * Spy glasses * Motion sensor * Access management * Animations & props * Take & save photos as item * DUI for photos * Device manager ### Installation *** * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-spy` to your server cfg after no-base. # Configuration Source: https://docs.nonefivem.com/scripts/no-torture/configuration ## Options *** You can find config file in `no-torture/config/sh_config.lua` | Option | type | Description | | ---------------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | EnableInteractionZones | boolean | Enables interaction zones. Set this to true if you don't have an interaction (target) resource. | | PlacementCommand | string? | Command to start dynamic chair placement. | | ItemName | string? | Item to start dynamic chair placement. | | SaveDynamicChairs | boolean | Whether to save dynamic chairs to the database. Set this to false if you don't have a mysql resource. | | SceneRenderDistance | number | Distance between player and torture chair to create the scene. | | Controls | `[key: string]: {index: number; label: string}` | [FiveM key controls](https://docs.fivem.net/docs/game-references/controls/#controls) | | StaticChairs | `{coords: vector3; h: number}[]` | List of static chairs. | # Exports & Events Source: https://docs.nonefivem.com/scripts/no-torture/exports-and-events ## Client Net Events Starts dynamic chair placement. # Introduction Source: https://docs.nonefivem.com/scripts/no-torture/index FiveM resource for torture. [Tebex Page](https://store.nonefivem.com/packages/5963928). This resource is only available via monthly subscription or ALL-IN-ONE bundle. ## Features *** * Players can torture each other. * Static & dynamic chairs. * Synchronized animations, props, sound effects & particles. * Torture cam. * 4 different torture types: * Electrocute * Tooth pull * Water board * Wrench * Sync with other players. ## Installation *** * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-torture` to your server.cfg after no-base. # Configuration Source: https://docs.nonefivem.com/scripts/no-trains/configuration ## Options *** You can find config file in `no-trains/config/sh_config.lua` | Option | type | Description | | ------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------ | | SpawnRate | EXTREMELY\_LOW \| VERY\_LOW \| LOW \| NORMAL \| HIGH \| VERY\_HIGH \| EXTREMELY\_HIGH | Spawn rate for trains and metros. | | MaxMetroCount | number | Limits the maximum active metros. | | MaxTrainCount | number | Limits the maximum active trains. | | KeepDoorsOpenWhenInside | boolean | Keeps metro doors open if player is inside. | | ForceDoorsOpenWhenStopped | boolean | Opens metro doors when metro is stopped. | | StationBlip | `{Enabled: boolean; Scale: number; Sprite: Number; Color: Number}` | [Blips](https://docs.fivem.net/docs/game-references/blips/). | # Exports & Events Source: https://docs.nonefivem.com/scripts/no-trains/exports-and-events ## Server Exports Enables next train spawns. Disables next train spawns. **Parameters** * destroyAll: boolean Destroy all the trains and metros. Returns current train count. **Returns** * count: number Returns current metro count. **Returns** * count: number # Introduction Source: https://docs.nonefivem.com/scripts/no-trains/index FiveM resource for synchronised trains. [Tebex Page](https://store.nonefivem.com/packages/6189564). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-trains` to your server.cfg after no-base. # Anchor Source: https://docs.nonefivem.com/scripts/no-vehicles/configuration/anchor ## Options *** You can find config file in `no-vehicles/config/sh_anchor.lua` | Option | type | Description | | ---------------- | ------- | ----------------------------------------------------- | | Enabled | boolean | Enable or disable anchor feature. | | MaxSpeed | number | Maximum speed to anchor the boat. | | Key | string | Default key to toggle anchor, leave empty to disable. | | Command | string | Command to toggle anchor, leave empty to disable. | | NotificationIcon | string | Notification icon | # Cruise Source: https://docs.nonefivem.com/scripts/no-vehicles/configuration/cruise ## Options *** You can find config file in `no-vehicles/config/sh_cruise.lua` | Option | type | Description | | ---------------- | --------- | ------------------------------------------------------------------------------------- | | Enabled | boolean | Enable or disable cruise feature. | | Keys | string\[] | Default keys to toggle, increase and decrease cruise control, leave empty to disable. | | Command | string | Command to toggle cruise control, leave empty to disable. | | NotificationIcon | string | Notification icon | # Configuration Source: https://docs.nonefivem.com/scripts/no-vehicles/configuration/index ## Options *** You can find config file in `no-vehicles/config/sh_config.lua` | Option | type | Description | | --------------- | ---------- | ------------------------------------------------------- | | SpeedUnit | kph \| mph | Speed unit to use it across the script. Default is kph. | | FireTruckModels | number\[] | Add any custom fire truck models for sirens. | # Indicators Source: https://docs.nonefivem.com/scripts/no-vehicles/configuration/indicators ## Options *** You can find config file in `no-vehicles/config/sh_indicator.lua` | Option | type | Description | | ------- | --------- | -------------------------------------------------------------------------- | | Enabled | boolean | Enable or disable indicator feature. | | Keys | string\[] | Default keys to set left, right and hazard lights, leave empty to disable. | # Roll Source: https://docs.nonefivem.com/scripts/no-vehicles/configuration/roll ## Options *** You can find config file in `no-vehicles/config/sh_roll.lua` | Option | type | Description | | ---------------- | ------- | ------------------------------------------------ | | Enabled | boolean | Enable or disable roll control feature. | | MaxRoll | number | Maximum roll angle to enable roll control. | | MaxSpeed | number | Max speed to enable roll control. | | FlipCommand | string | Command to flip vehicle, leave empty to disable. | | NotificationIcon | string | Notification icon. | # Seatbelt Source: https://docs.nonefivem.com/scripts/no-vehicles/configuration/seatbelt ## Options *** You can find config file in `no-vehicles/config/sh_seatbelt.lua` | Option | type | Description | | --------------------------- | ------- | -------------------------------------------------------- | | Enabled | boolean | Enable or disable seatbelt feature. | | SeatBeltOnDamageMultiplier | number | Damage multiplier when seat belt is on. | | SeatBeltOffDamageMultiplier | number | Damage multiplier when seat belt is off. | | Key | string | Default key to toggle seat belt, leave empty to disable. | | Command | string | Command to toggle seat belt, leave empty to disable. | | NotificationIcon | string | Notification Icon | # Siren Lights Source: https://docs.nonefivem.com/scripts/no-vehicles/configuration/siren-lights ## Options *** You can find config file in `no-vehicles/config/sh_sirenlights.lua` | Option | type | Description | | ------- | ------- | ----------------------------------------------------------- | | Enabled | boolean | Enable or disable siren lights feature. | | Key | string | Default key to toggle siren lights, leave empty to disable. | | Command | string | Command to toggle siren lights, leave empty to disable. | # Siren Sounds Source: https://docs.nonefivem.com/scripts/no-vehicles/configuration/siren-sounds ## Options *** You can find config file in `no-vehicles/config/sh_sirensounds.lua` | Option | type | Description | | ------- | --------- | ----------------------------------------------------------------------------- | | Enabled | boolean | Enable or disable siren sounds feature. | | Keys | string\[] | Default keys to toggle siren, switch sirens and horn, leave empty to disable. | | Command | string | Command to toggle siren lights, leave empty to disable. | # Exports & Events Source: https://docs.nonefivem.com/scripts/no-vehicles/exports-and-events ## Client Exports Toggles the boat anchor if it's available. Toggles the cruise limit. Flips the given vehicle. **Parameters** * vehicle: number Toggles the seat belt if active. Returns true if the player is in a vehicle with a seat belt. Returns true if player wears seat belt. ## Client Events Toggles the boat anchor if it's available. Toggles the cruise limit. Flips the given vehicle. **Parameters** * vehicle: number Toggles the seat belt if active. Triggered by us when player get in a vehicle with a seat belt. **Parameters** * status: boolean Triggered by us when player puts on the seat belt. **Parameters** * status: boolean # Introduction Source: https://docs.nonefivem.com/scripts/no-vehicles/index FiveM resource for vehicle features. [Tebex Page](https://store.nonefivem.com/packages/6548547). ### Installation * Make sure you've installed [no-base](/no-base/#installation) correctly. * Download your resource from [CFX.re portal](https://portal.cfx.re/assets/granted-assets). * Drag & drop your resource to `resources/[none]` * Add `ensure no-vehicles` to your server.cfg after no-base.