UZ Scripts
uz_AutoShot

Integration Examples

Real-world code examples showing how to integrate uz_AutoShot thumbnails into clothing scripts, shops, and NUI panels.

Integration Examples

These examples show how to use uz_AutoShot's HTTP API and exports in real-world scenarios. All examples fetch photos directly from the local HTTP server — no file copying or Lua proxy needed.


NUI Callback (Lua → 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 Fetch (JS only)

Since the HTTP server has CORS enabled, you can skip Lua entirely:

// Fetch all male tops
async function getClothingItems(gender, type, id) {
  const res = await fetch(
    `http://127.0.0.1:3959/api/manifest/${gender}/${type}/${id}`
  )
  if (!res.ok) return []
  const data = await res.json()
  return data.items
}

// Usage
const tops = await getClothingItems('male', 'component', 11)
const hats = await getClothingItems('male', 'prop', 0)

React — Thumbnail Grid

A complete React component that fetches and displays clothing thumbnails:

import { useState, useEffect } from 'react'

const API_BASE = 'http://127.0.0.1:3959'

function ClothingGrid({ gender, type, categoryId }) {
  const [items, setItems] = useState([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    setLoading(true)
    fetch(`${API_BASE}/api/manifest/${gender}/${type}/${categoryId}`)
      .then(res => res.json())
      .then(data => {
        setItems(data.items || [])
        setLoading(false)
      })
      .catch(() => setLoading(false))
  }, [gender, type, categoryId])

  if (loading) return <div className="loading">Loading...</div>
  if (!items.length) return <div className="empty">No photos captured yet</div>

  return (
    <div className="clothing-grid">
      {items.map((item) => (
        <button
          key={`${item.drawable}_${item.texture}`}
          className="clothing-item"
          onClick={() => applyClothing(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;
}

React — Category Selector with Thumbnails

A full clothing browser with category tabs and thumbnail grid:

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

const API_BASE = 'http://127.0.0.1:3959'

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' },
]

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(`${API_BASE}/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'

const API_BASE = 'http://127.0.0.1:3959'

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(`${API_BASE}/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 in any component:
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(`${API_BASE}/api/exists?${params}`)
  const data = await res.json()
  return data.exists
}

// Usage
const exists = await hasPhoto('male', 'component', 11, 5)
if (exists) {
  img.src = `http://127.0.0.1:3959/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)

On this page