# Prompt Anim Core - Documentation

Complete documentation for the gym equipment system with advanced location management, dynamic equipment spawning, and boxing ring features.

---

## Table of Contents

- [Overview](#overview)
- [Configuration](#configuration)
  - [Location Structure](#location-structure)
  - [Clear Location Feature](#clear-location-feature)
  - [Equipment Types](#equipment-types)
  - [Boxing Ring](#boxing-ring)
- [Exports API](#exports-api)
  - [Location Management](#location-management)
  - [Equipment Management](#equipment-management)
  - [Utility Functions](#utility-functions)
- [Usage Examples](#usage-examples)
- [Advanced Features](#advanced-features)

---

## Overview

Prompt Anim Core is a comprehensive gym equipment system for FiveM that provides:
- Dynamic gym location management
- Multiple equipment types with synchronized animations
- Boxing ring for PvP matches
- Automatic object clearing for gym locations
- Integration with ox_target and ox_lib
- Client-server synchronization
- Resource-based cleanup

---

## Configuration

### Location Structure

Locations are defined in `config/config_c.lua` under the `locations` table:

```lua
locations = {
    ['location_name'] = {
        coords = vec3(x, y, z),           -- Required: Center point of the gym
        renderDistance = 100.0,            -- Optional: Custom render distance (default from main config)
        
        clearLocation = {                  -- Optional: Clear default objects from location
            radius = 20.0,                 -- Radius around coords to clear objects
            additionalObjects = {          -- Additional models to clear (beyond clearLocationModels)
                "prop_custom_model_1",
                "prop_custom_model_2"
            }
        },
        
        props = {                          -- Equipment to spawn at this location
            speedbag = {
                vec4(x, y, z, heading),
                vec4(x, y, z, heading)
            },
            leg_press = {
                vec4(x, y, z, heading)
            },
            bench = {
                -- Simple format: bar attaches to player
                vec4(x, y, z, heading),
                -- Extended format: bar spawns at fixed position
                {coords = vec4(x, y, z, h), bar = vec4(x, y, z, h)}
            }
        }
    }
}
```

#### Location Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `coords` | `vector3` | ✅ | Center coordinates of the gym location |
| `renderDistance` | `number` | ❌ | Custom render distance (overrides global setting) |
| `clearLocation` | `table` | ❌ | Configuration for clearing default objects |
| `props` | `table` | ❌ | Equipment to spawn at this location |

### Clear Location Feature

The `clearLocation` feature automatically hides default game objects (like vanilla gym equipment) when players enter your custom gym location.

```lua
clearLocation = {
    radius = 20.0,              -- Search radius around location coords
    additionalObjects = {       -- Additional models to hide
        "your_custom_model",
        "another_model"
    }
}
```

**How it works:**
1. When a player enters the gym location, the system searches for objects within the specified radius
2. Objects matching models from `clearLocationModels` (global) and `additionalObjects` (local) are hidden
3. Hidden objects are tracked and automatically restored when the player leaves
4. Objects are also restored on script restart

**Global Clear Models** (defined in `clearLocationModels`):
- Bench press variants (`prop_muscle_bench_*`)
- Exercise bikes (`prop_exer_bike_*`)
- Weight equipment (`prop_weight_*`, `prop_barbell_*`)
- Yoga mats (`prop_yoga_mat_*`)
- Pull-up bars and dip bars
- Prison gym equipment

### Equipment Types

Available equipment types with their configurations:

| Equipment Type | Model | Description |
|---------------|-------|-------------|
| `bench` | `vision_gymbarbell` | Bench press (supports bar attachment) |
| `vin_chu` | `vin_chu` | Pull-up bar |
| `leg_press` | `vision_gymlegpress` | Leg press machine |
| `speedbag` | `vision_gymspeedbagwall` | Wall-mounted speed bag |
| `gymbike` | `vision_gymbike` | Stationary bike |
| `gymlatpull` | `vision_gymlatpull` | Lat pulldown machine |
| `gympullmachine1` | `vision_gympullmachine1` | Seated cable row |
| `gympullmachine2` | `vision_gympullmachine2` | Chest press machine |
| `gymrowpull` | `vision_gymrowpull` | Rowing pull machine |
| `gymspeedbag` | `vision_gymspeedbag` | Free-standing speed bag |

Each equipment type includes:
- `model` - Prop model hash/name
- `animations` - Object animation dictionaries
- `playerAnimation` - Player animation and positioning
- `repetitions` - Number of exercise repetitions
- `prop` - Optional attached props (e.g., barbell)

### Boxing Ring

Boxing ring configuration for PvP matches:

```lua
boxingRing = {
    enable = true,                          -- Enable/disable boxing ring feature
    model = "vision_gymboxingring",         -- Boxing ring model
    coords = {                              -- Spawn locations
        vec4(x, y, z, heading),
        vec4(x, y, z, heading)
    }
}
```

---

## Exports API

### Location Management

#### `CreateGymLocation`

Creates a new gym location with optional equipment.

```lua
exports['prompt_anim_core']:CreateGymLocation(locationName, data)
```

**Parameters:**
- `locationName` (string) - Unique identifier for the location
- `data` (table) - Location configuration
  - `coords` (vector3) **Required** - Center point coordinates
  - `renderDistance` (number) - Optional custom render distance
  - `clearLocation` (table) - Optional object clearing configuration
    - `radius` (number) - Clearing radius
    - `additionalObjects` (string[]) - Additional models to clear
  - `props` (table) - Optional equipment configuration
    - Key: Equipment type name
    - Value: Array of vector4 coordinates

**Returns:**
- `success` (boolean) - True if location was created
- `error` (string?) - Error message if creation failed

**Example:**
```lua
local success, error = exports['prompt_anim_core']:CreateGymLocation('sandy_gym', {
    coords = vec3(1850.0, 3700.0, 34.0),
    renderDistance = 100.0,
    clearLocation = {
        radius = 25.0,
        additionalObjects = {
            "prop_old_gym_equipment"
        }
    },
    props = {
        speedbag = {
            vec4(1855.0, 3705.0, 34.0, 90.0),
            vec4(1855.0, 3707.0, 34.0, 90.0)
        },
        leg_press = {
            vec4(1860.0, 3700.0, 34.0, 180.0)
        }
    }
})

if not success then
    print("Error creating gym: " .. (error or "unknown"))
end
```

---

#### `RemoveGymLocation`

Removes an entire gym location and all its equipment.

```lua
exports['prompt_anim_core']:RemoveGymLocation(locationName)
```

**Parameters:**
- `locationName` (string) - Location identifier to remove

**Returns:**
- `success` (boolean) - True if location was removed

**Example:**
```lua
local success = exports['prompt_anim_core']:RemoveGymLocation('sandy_gym')
```

---

### Equipment Management

#### `AddEquipmentToLocation`

Adds equipment to an existing gym location.

```lua
exports['prompt_anim_core']:AddEquipmentToLocation(locationName, equipmentType, coords)
```

**Parameters:**
- `locationName` (string) - Target location identifier
- `equipmentType` (string) - Type of equipment to add
- `coords` (vector4 or vector4[]) - Single position or array of positions

**Returns:**
- `success` (boolean) - True if equipment was added
- `count` (number?) - Number of equipment pieces added

**Example:**
```lua
-- Add single equipment
local success, count = exports['prompt_anim_core']:AddEquipmentToLocation(
    'sandy_gym',
    'leg_press',
    vec4(100.0, 200.0, 50.0, 180.0)
)

-- Add multiple equipment at once
local success, count = exports['prompt_anim_core']:AddEquipmentToLocation(
    'sandy_gym',
    'speedbag',
    {
        vec4(100.0, 200.0, 50.0, 90.0),
        vec4(100.0, 202.0, 50.0, 90.0),
        vec4(100.0, 204.0, 50.0, 90.0)
    }
)

print(string.format("Added %d pieces of equipment", count))
```

---

#### `RemoveEquipmentFromLocation`

Removes equipment from a gym location.

```lua
exports['prompt_anim_core']:RemoveEquipmentFromLocation(locationName, equipmentType, coords, tolerance)
```

**Parameters:**
- `locationName` (string) - Target location identifier
- `equipmentType` (string) - Type of equipment to remove
- `coords` (vector4 or vector4[] or nil) - Specific positions to remove, or nil to remove all
- `tolerance` (number?) - Distance tolerance for position matching (default: 0.1)

**Returns:**
- `success` (boolean) - True if equipment was removed
- `count` (number?) - Number of equipment pieces removed

**Example:**
```lua
-- Remove all leg presses from location
local success, count = exports['prompt_anim_core']:RemoveEquipmentFromLocation(
    'sandy_gym',
    'leg_press',
    nil
)

-- Remove specific equipment by position (with tolerance)
local success, count = exports['prompt_anim_core']:RemoveEquipmentFromLocation(
    'sandy_gym',
    'speedbag',
    vec4(100.0, 200.0, 50.0, 90.0),
    0.5  -- 0.5 meter tolerance
)

print(string.format("Removed %d pieces of equipment", count))
```

---

### Utility Functions

#### `GetLocationEquipment`

Retrieves all equipment at a specific location.

```lua
exports['prompt_anim_core']:GetLocationEquipment(locationName)
```

**Parameters:**
- `locationName` (string) - Location identifier

**Returns:**
- `equipment` (table<string, vector4[]>?) - Map of equipment types to position arrays, or nil if location doesn't exist

**Example:**
```lua
local equipment = exports['prompt_anim_core']:GetLocationEquipment('sandy_gym')
if equipment then
    for equipmentType, positions in pairs(equipment) do
        print(string.format("%s: %d pieces", equipmentType, #positions))
        for i, pos in ipairs(positions) do
            print(string.format("  #%d: %.2f, %.2f, %.2f (heading: %.2f)", 
                i, pos.x, pos.y, pos.z, pos.w))
        end
    end
end
```

---

#### `GetAllLocations`

Returns all gym locations and their data.

```lua
exports['prompt_anim_core']:GetAllLocations()
```

**Returns:**
- `locations` (table<string, table>) - Map of location names to location data

**Example:**
```lua
local locations = exports['prompt_anim_core']:GetAllLocations()
for locationName, locationData in pairs(locations) do
    print(string.format("Location: %s at %s", locationName, locationData.coords))
    if locationData.clearLocation then
        print(string.format("  Clear radius: %.2f", locationData.clearLocation.radius))
    end
end
```

---

#### `GetAvailableEquipmentTypes`

Returns all available equipment types defined in the configuration.

```lua
exports['prompt_anim_core']:GetAvailableEquipmentTypes()
```

**Returns:**
- `types` (string[]) - Array of equipment type names

**Example:**
```lua
local types = exports['prompt_anim_core']:GetAvailableEquipmentTypes()
print("Available equipment types:")
for _, equipmentType in ipairs(types) do
    print("  - " .. equipmentType)
end
-- Output: bench, vin_chu, leg_press, speedbag, gymbike, etc.
```

---

## Usage Examples

### Creating a Complete Gym on Resource Start

```lua
AddEventHandler('onResourceStart', function(resourceName)
    if GetCurrentResourceName() ~= resourceName then return end
    
    -- Create a new gym location with equipment and object clearing
    local success, error = exports['prompt_anim_core']:CreateGymLocation('custom_gym', {
        coords = vec3(500.0, 500.0, 100.0),
        renderDistance = 75.0,
        clearLocation = {
            radius = 30.0,
            additionalObjects = {
                "prop_old_equipment"
            }
        },
        props = {
            speedbag = {
                vec4(505.0, 505.0, 100.0, 90.0),
                vec4(505.0, 507.0, 100.0, 90.0)
            },
            leg_press = {
                vec4(510.0, 500.0, 100.0, 180.0)
            },
            gymbike = {
                vec4(515.0, 498.0, 100.0, 270.0),
                vec4(515.0, 500.0, 100.0, 270.0)
            },
            bench = {
                -- Simple format: bar attaches to player
                vec4(520.0, 505.0, 100.0, 0.0),
                -- Extended format: bar at fixed position
                {
                    coords = vec4(520.0, 510.0, 100.0, 0.0),
                    bar = vec4(520.0, 510.0, 100.8, 0.0)
                }
            }
        }
    })
    
    if success then
        print("Custom gym created successfully!")
    else
        print("Failed to create gym: " .. (error or "unknown error"))
    end
end)
```

### Dynamic Equipment Management

```lua
-- Add equipment dynamically during gameplay
RegisterCommand('addgymequip', function(source, args)
    local equipmentType = args[1] or 'speedbag'
    local coords = GetEntityCoords(PlayerPedId())
    local heading = GetEntityHeading(PlayerPedId())
    
    local success, count = exports['prompt_anim_core']:AddEquipmentToLocation(
        'custom_gym',
        equipmentType,
        vec4(coords.x, coords.y, coords.z, heading)
    )
    
    if success then
        print(string.format("Added %d x %s", count, equipmentType))
    else
        print("Failed to add equipment")
    end
end)

-- Remove nearby equipment
RegisterCommand('removegymequip', function(source, args)
    local equipmentType = args[1] or 'speedbag'
    local coords = GetEntityCoords(PlayerPedId())
    
    local success, count = exports['prompt_anim_core']:RemoveEquipmentFromLocation(
        'custom_gym',
        equipmentType,
        vec4(coords.x, coords.y, coords.z, 0.0),
        5.0  -- 5 meter tolerance
    )
    
    if success then
        print(string.format("Removed %d x %s", count, equipmentType))
    else
        print("Failed to remove equipment")
    end
end)
```

### Automatic Cleanup on Resource Stop

```lua
AddEventHandler('onResourceStop', function(resourceName)
    if GetCurrentResourceName() ~= resourceName then return end
    
    -- Cleanup is automatic, but you can manually remove if needed
    exports['prompt_anim_core']:RemoveGymLocation('custom_gym')
    print("Gym cleaned up")
end)
```

### Inspecting Gym Locations

```lua
RegisterCommand('listgyms', function()
    local locations = exports['prompt_anim_core']:GetAllLocations()
    
    print("=== Gym Locations ===")
    for locationName, locationData in pairs(locations) do
        print(string.format("\nLocation: %s", locationName))
        print(string.format("  Coords: %s", locationData.coords))
        print(string.format("  Render Distance: %.2f", locationData.renderDistance or 100.0))
        
        if locationData.clearLocation then
            print(string.format("  Clear Radius: %.2f", locationData.clearLocation.radius))
            if locationData.clearLocation.additionalObjects then
                print(string.format("  Additional Clear Objects: %d", #locationData.clearLocation.additionalObjects))
            end
        end
        
        local equipment = exports['prompt_anim_core']:GetLocationEquipment(locationName)
        if equipment then
            local totalEquipment = 0
            for equipType, positions in pairs(equipment) do
                totalEquipment = totalEquipment + #positions
                print(string.format("  - %s: %d units", equipType, #positions))
            end
            print(string.format("  Total Equipment: %d", totalEquipment))
        end
    end
end)
```

---

## Advanced Features

### Resource-Based Cleanup

The system automatically tracks which resource created each location and equipment. When a resource stops, all its gym locations and equipment are automatically removed and synchronized to all clients.

```lua
-- Resource A creates a gym
exports['prompt_anim_core']:CreateGymLocation('resource_a_gym', {...})

-- When Resource A stops, 'resource_a_gym' is automatically removed
```

### Multi-Format Bench Configuration

Benches support two coordinate formats:

```lua
-- Simple format: Barbell attaches to player during exercise
bench = {
    vec4(100.0, 200.0, 50.0, 0.0)
}

-- Extended format: Barbell spawns at fixed world position
bench = {
    {
        coords = vec4(100.0, 200.0, 50.0, 0.0),  -- Bench position
        bar = vec4(100.0, 200.0, 50.8, 0.0)       -- Barbell position
    }
}
```

### Client-Server Synchronization

All location and equipment changes are automatically synchronized to all connected clients via networked events:
- `gym:locationCreated` - New location added
- `gym:locationRemoved` - Location removed
- `gym:refreshLocation` - Location equipment updated

### Interaction Systems

The script supports multiple interaction systems (configured in `config_c.lua`):
- `auto` - Automatically detects ox_target or falls back to textUI
- `ox_target` - Uses ox_target for equipment interaction
- `textUI` - Uses ox_lib text prompts
- `custom` - Implement your own interaction system

### Custom Progress Bar

You can implement custom progress bar displays:

```lua
progressBar = 'custom',
customProgressBar = function(machine, duration)
    -- Your custom progress bar implementation
    exports['your-progress']:Start(duration)
    return true  -- Return true when completed
end
```

---

## Notes

- All coordinates use `vector3` for positions and `vector4` (x, y, z, heading) for positioned objects
- Equipment and locations are automatically synchronized across all clients
- The `clearLocation` feature only hides objects; they are restored when players leave or the script restarts
- Blips are automatically created for each location if `blip.enable = true`
- Equipment created by a resource is automatically cleaned up when that resource stops
- All distance values are in meters
- Headings are in degrees (0-360)

---

**Version:** 1.0  
**Dependencies:** ox_lib (required), ox_target (optional)  
**License:** As per resource license
