UZ Scripts
uz_AutoShot

Integration Examples

Code examples showing how to integrate uz_AutoShot thumbnails into clothing scripts, vehicle shops, and NUI panels.

Integration Examples

These examples show how to use uz_AutoShot's API and exports in real-world scenarios. Photos are served via FiveM's cfx-nui protocol, while metadata is available through the HTTP API.


NUI Callback (Lua to JS)

The simplest way to pass the API URL from Lua to your NUI:

-- client.lua (your clothing script)
RegisterNUICallback('getClothingPhotos', function(data, cb)
    local url = exports['uz_AutoShot']:getManifestURL(data.gender, data.type, data.id)

    PerformHttpRequest(url, function(status, body)
        if status ~= 200 then
            cb({ items = {} })
            return
        end

        local decoded = json.decode(body)
        cb({ items = decoded and decoded.items or {} })
    end, 'GET')
end)
// nui/script.js
const response = await fetch(
  `https://cfx-nui-YOUR_SCRIPT/getClothingPhotos`,
  {
    method: 'POST',
    body: JSON.stringify({ gender: 'male', type: 'component', id: 11 })
  }
)
const { items } = await response.json()

This approach routes through Lua. For better performance, fetch directly from JS. See the next example.


Direct Photo URL (cfx-nui)

Photos are accessible directly via cfx-nui protocol, no HTTP server needed for images:

// Build photo URL directly
function getPhotoUrl(gender, type, id, drawable, texture = 0) {
  const prefix = type === 'prop' ? `prop_${id}`
    : type === 'overlay' ? `overlay_${id}`
    : `${id}`
  const texSuffix = type === 'overlay' ? '' : (texture > 0 ? `_${texture}` : '')
  return `https://cfx-nui-uz_AutoShot/shots/${gender}/${prefix}/${drawable}${texSuffix}.png`
}

// Clothing
getPhotoUrl('male', 'component', 11, 5, 0)
// → 'https://cfx-nui-uz_AutoShot/shots/male/11/5_0.png'

// Overlay
getPhotoUrl('male', 'overlay', 1, 3)
// → 'https://cfx-nui-uz_AutoShot/shots/male/overlay_1/3.png'

// Vehicle and object URLs use a simpler pattern
function getVehicleUrl(model) {
  return `https://cfx-nui-uz_AutoShot/shots/vehicles/${model}.png`
}

function getObjectUrl(model) {
  return `https://cfx-nui-uz_AutoShot/shots/objects/${model}.png`
}

React: Thumbnail Grid

A React component that displays clothing thumbnails:

import { useState, useEffect } from 'react'

const SHOTS_BASE = 'https://cfx-nui-uz_AutoShot/shots'

function ClothingGrid({ gender, type, categoryId, numDrawables }) {
  const prefix = type === 'prop' ? `prop_${categoryId}`
    : type === 'overlay' ? `overlay_${categoryId}`
    : categoryId

  const items = Array.from({ length: numDrawables }, (_, i) => ({
    drawable: i,
    texture: 0,
    url: `${SHOTS_BASE}/${gender}/${prefix}/${i}.png`,
  }))

  if (!items.length) return <div className="empty">No items available</div>

  return (
    <div className="clothing-grid">
      {items.map((item) => (
        <button
          key={item.drawable}
          className="clothing-item"
          onClick={() => applyClothing({ type, id: categoryId, ...item })}
        >
          <img
            src={item.url}
            alt={`Drawable ${item.drawable}`}
            loading="lazy"
          />
          <span>{item.drawable}</span>
        </button>
      ))}
    </div>
  )
}

function applyClothing(item) {
  fetch(`https://cfx-nui-YOUR_SCRIPT/applyClothing`, {
    method: 'POST',
    body: JSON.stringify({
      itemType: item.type,
      id: item.id,
      drawable: item.drawable,
      texture: item.texture,
    }),
  })
}
.clothing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 8px;
  padding: 12px;
}

.clothing-item {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  padding: 4px;
  cursor: pointer;
  transition: border-color 0.15s;
}

.clothing-item:hover {
  border-color: rgba(255, 255, 255, 0.3);
}

.clothing-item img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
}

Display vehicle thumbnails from uz_AutoShot:

const SHOTS_BASE = 'https://cfx-nui-uz_AutoShot/shots'

function VehicleGallery({ vehicles }) {
  return (
    <div className="clothing-grid">
      {vehicles.map((model) => (
        <button key={model} className="clothing-item" onClick={() => spawnVehicle(model)}>
          <img
            src={`${SHOTS_BASE}/vehicles/${model}.png`}
            alt={model}
            loading="lazy"
          />
          <span>{model}</span>
        </button>
      ))}
    </div>
  )
}

function spawnVehicle(model) {
  fetch(`https://cfx-nui-YOUR_SCRIPT/spawnVehicle`, {
    method: 'POST',
    body: JSON.stringify({ model }),
  })
}

React: Category Selector with Thumbnails

A full clothing browser with category tabs and thumbnail grid:

import { useState, useEffect, useCallback } from 'react'

const CATEGORIES = [
  { type: 'component', id: 11, label: 'Tops' },
  { type: 'component', id: 4,  label: 'Pants' },
  { type: 'component', id: 6,  label: 'Shoes' },
  { type: 'component', id: 1,  label: 'Masks' },
  { type: 'component', id: 8,  label: 'Undershirt' },
  { type: 'prop',      id: 0,  label: 'Hats' },
  { type: 'prop',      id: 1,  label: 'Glasses' },
  { type: 'overlay',   id: 1,  label: 'Facial Hair' },
  { type: 'overlay',   id: 2,  label: 'Eyebrows' },
  { type: 'overlay',   id: 4,  label: 'Makeup' },
]

function ClothingBrowser({ gender = 'male' }) {
  const [activeCategory, setActiveCategory] = useState(CATEGORIES[0])
  const [items, setItems] = useState([])
  const [selected, setSelected] = useState(null)

  useEffect(() => {
    const { type, id } = activeCategory
    fetch(`http://127.0.0.1:3959/api/manifest/${gender}/${type}/${id}`)
      .then(res => res.json())
      .then(data => setItems(data.items || []))
      .catch(() => setItems([]))
  }, [gender, activeCategory])

  const handleApply = useCallback((item) => {
    setSelected(item.drawable)
    fetch(`https://cfx-nui-YOUR_SCRIPT/applyClothing`, {
      method: 'POST',
      body: JSON.stringify({
        itemType: item.type,
        id: item.id,
        drawable: item.drawable,
        texture: item.texture,
      }),
    })
  }, [])

  return (
    <div className="clothing-browser">
      <div className="categories">
        {CATEGORIES.map((cat) => (
          <button
            key={`${cat.type}_${cat.id}`}
            className={activeCategory === cat ? 'active' : ''}
            onClick={() => setActiveCategory(cat)}
          >
            {cat.label}
          </button>
        ))}
      </div>

      <div className="items-grid">
        {items.map((item) => (
          <button
            key={`${item.drawable}_${item.texture}`}
            className={`item ${selected === item.drawable ? 'selected' : ''}`}
            onClick={() => handleApply(item)}
          >
            <img src={item.url} alt={`#${item.drawable}`} loading="lazy" />
          </button>
        ))}
      </div>
    </div>
  )
}

React: Custom Hook

A reusable hook for fetching clothing data:

import { useState, useEffect } from 'react'

export function useClothingItems(gender, type, categoryId) {
  const [items, setItems] = useState([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)

  useEffect(() => {
    if (!gender || !type || categoryId === undefined) return

    setLoading(true)
    setError(null)

    fetch(`http://127.0.0.1:3959/api/manifest/${gender}/${type}/${categoryId}`)
      .then(res => {
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        return res.json()
      })
      .then(data => {
        setItems(data.items || [])
        setLoading(false)
      })
      .catch(err => {
        setError(err.message)
        setItems([])
        setLoading(false)
      })
  }, [gender, type, categoryId])

  return { items, loading, error }
}

// Usage:
function TopsGrid() {
  const { items, loading, error } = useClothingItems('male', 'component', 11)

  if (loading) return <Spinner />
  if (error) return <p>Error: {error}</p>

  return (
    <div className="grid">
      {items.map(item => (
        <img key={item.drawable} src={item.url} alt={`#${item.drawable}`} />
      ))}
    </div>
  )
}

Check if Photo Exists

Before displaying a thumbnail, check if it was captured:

async function hasPhoto(gender, type, id, drawable, texture = 0) {
  const params = new URLSearchParams({ gender, type, id, drawable, texture })
  const res = await fetch(`http://127.0.0.1:3959/api/exists?${params}`)
  const data = await res.json()
  return data.exists
}

// Clothing
const exists = await hasPhoto('male', 'component', 11, 5)
if (exists) {
  img.src = `https://cfx-nui-uz_AutoShot/shots/male/11/5_0.png`
} else {
  img.src = '/placeholder.png'
}

Lua: Clothing Shop Integration

Example for a clothing shop script that uses uz_AutoShot photos:

-- Open shop with thumbnails from uz_AutoShot
RegisterCommand('clothingshop', function()
    local ped = PlayerPedId()
    local gender = (GetEntityModel(ped) == GetHashKey('mp_m_freemode_01')) and 'male' or 'female'

    -- Build photo URLs for all tops
    local items = {}
    local numDrawables = GetNumberOfPedDrawableVariations(ped, 11)

    for i = 0, numDrawables - 1 do
        items[#items + 1] = {
            drawable = i,
            price = math.random(100, 5000),
            photo = exports['uz_AutoShot']:getPhotoURL(gender, 'component', 11, i, 0)
        }
    end

    -- Send to NUI
    SendNUIMessage({
        type = 'openShop',
        category = 'Tops',
        items = items,
    })
    SetNuiFocus(true, true)
end)

Lua: Vehicle Dealership Integration

Use vehicle photos in a dealership script:

RegisterCommand('dealership', function()
    local vehicles = {}
    local models = GetAllVehicleModels()

    for _, modelName in ipairs(models) do
        local hash = GetHashKey(modelName)
        local classId = GetVehicleClassFromName(hash)

        vehicles[#vehicles + 1] = {
            model = modelName,
            class = classId,
            price = math.random(10000, 500000),
            photo = exports['uz_AutoShot']:getVehiclePhotoURL(modelName)
        }
    end

    SendNUIMessage({
        type = 'openDealership',
        vehicles = vehicles,
    })
    SetNuiFocus(true, true)
end)

On this page