> For the complete documentation index, see [llms.txt](https://davedev.gitbook.io/wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://davedev.gitbook.io/wiki/immersive-flashlight/info/main-installation.md).

# Main Installation

## <i class="fa-brain">:brain:</i> Information

This page walks through a clean install of `DaveDev_Flashlight` and the optional `DaveDev_SFX` resource and includes a configuration guide for a quick and painless experience.

### <i class="fa-box-open">:box-open:</i> What's included

* `DaveDev_Flashlight` - the gameplay logic, framework adapters, commands, and client/server exports.
* `DaveDev_SFX` - a fallback that can be used in place of Interact-Sound. Keep it beside the flashlight unless you already use `xsound` or `interact-sound` and have copied the audio to their respective folders. ***If so, you can safely delete our bundled SFX resource!***

***

#### <i class="fa-message-exclamation">:message-exclamation:</i> Prerequisites

* A working FXServer on a current recommended artifact.
* No framework is required for standalone command/export use.
* Optional supported cores: `qbx_core`, `qb-core`, `ox_core`, or `es_extended`.
* Optional supported inventories: `ox_inventory`, a QBCore/QB-compatible inventory, `qs-inventory`, ESX inventory, or a custom inventory bridge.
* Optional notifications: `ox_lib`, QBCore notifications, chat, or a custom notification event/handler.
* Audio: `interact-sound`, the included `DaveDev_SFX`, or audio disabled in `config.lua`.

{% hint style="info" %}
It is safe to leave `DaveDev_SFX` installed when `interact-sound` is running. The fallback resource detects `interact-sound` and stops itself to prevent double playback.
{% endhint %}

***

### <i class="fa-folder">:folder:</i> Folder placement

Place both resources inside `resources` without renaming:

```
resources/
  [DaveDev]/
    DaveDev_Flashlight/
    DaveDev_SFX/          # optional fallback
```

Keep the folder names exactly as shipped unless you update the `resource` names in `config.lua` under the `sfx` and `framework` blocks.

***

#### <i class="fa-rectangle-code">:rectangle-code:</i> Server.cfg order

Start the core and inventory resources used by your server before the flashlight. Only include the lines that apply to your stack.

```cfg
# Core/framework examples - choose the one your server uses
ensure qbx_core           # Qbox
# ensure qb-core          # QBCore
# ensure ox_core          # ox_core
# ensure es_extended      # ESX

# Inventory examples - choose the one your server uses
ensure ox_inventory
# ensure qs-inventory

# Optional audio providers
ensure xsound             # external provider, if installed
ensure interact-sound     # external provider, if installed
ensure DaveDev_SFX        # included fallback; stops itself if interact-sound is active (CAN BE DELETED)

ensure DaveDev_Flashlight
```

{% hint style="success" %}
If you do not use `xsound` or `interact-sound`, keep `DaveDev_SFX` available or set `FlashlightConfig.sfx.enabled = false` if you want the flashlight to remain silent.
{% endhint %}

***

#### <i class="fa-arrow-progress">:arrow-progress:</i> Step-by-step install

1. Place `DaveDev_Flashlight` and the optional `DaveDev_SFX` resource in your resources folder without renaming them.
2. Start your framework and inventory before `DaveDev_Flashlight`.
3. Configure the simple `setup` block in `DaveDev_Flashlight/config.lua`:

```lua
setup = {
  core = 'auto',
  inventory = 'auto',
  itemNames = { 'flashlight' },
  requireItem = true,
  consumeOnUse = false,
  trustCustomUseEvent = false,
}
```

4. Add the configured item to your inventory when using inventory-driven access.
5. For ox\_inventory, add `client.export = 'DaveDev_Flashlight.useItem'` to the item definition.
6. Decide whether `/flashlight` and its keybind should remain enabled in addition to item usage.
7. Configure audio through `sfx.xsound`, `sfx.interactsound`, `sfx.builtin`, and `sfx.sounds`.
8. Restart the server and test equip/holster, beam toggle, remote synchronization, restrictions, and audio with at least two players.

{% hint style="info" %}
The advanced `framework.core` and `framework.inventory` sections are intended for renamed resources, forced adapter order, and custom integrations. Most installations should start with the simple `setup` block.
{% endhint %}

***

#### <i class="fa-gears">:gears:</i> Configuration Helper (`config.lua`)

{% hint style="info" %}
Start with the `setup`, `commands`, `sfx`, and `integrations` sections. Light, attachment, animation, and synchronization values are already tuned for the included assets and should be changed carefully.
{% endhint %}

{% stepper %}
{% step %}

#### Simple Setup

* `setup.core` selects core behavior: `auto`, `qbox`, `qbcore`, `ox`, `esx`, `standalone`, or `custom`.
* `setup.inventory` selects inventory behavior: `auto`, `ox_inventory`, `qb_inventory`, `qbox`, `qs_inventory`, `esx`, `standalone`, or `custom`.
* `setup.itemNames` lists every item name accepted by the resource.
* `setup.requireItem = true` requires the active inventory adapter to confirm ownership for commands and untrusted exports/events.
* `setup.consumeOnUse = true` removes an item through supported QB, QS, or ESX adapters. For ox\_inventory, configure consumption in the ox item definition.
* `setup.trustCustomUseEvent` must remain false unless the configured custom event is server-only and already verifies ownership.
  {% endstep %}

{% step %}

#### Debugging

* `debug = true` enables verbose client/server diagnostics.
* `debugTools.enabled = true` registers the `/flashlight_debug` troubleshooting command.
* `debugTools.ace` lists the ACE permissions allowed to run that command.
  {% endstep %}

{% step %}

#### Commands & Keybinds

* `commands.equip` controls `/flashlight` and the equip/holster keybind.
* `commands.equip.requireAce` can restrict the equip command to an ACE permission.
* `commands.equip.allowConsole` permits server-console use with a target player ID.
* `commands.toggleLight` controls `/flashlight_toggle` and the beam keybind.
* Set either `registerKeyMapping` value to false if another resource manages that binding.
  {% endstep %}

{% step %}

#### Item Behavior

* `items.metadataPassthrough` controls whether supported adapters forward item metadata and slot context.
* The simple `setup.itemNames` and `setup.requireItem` values take precedence over the legacy `items.names` and `items.requireItem` fields.
* When inventory resolves to `standalone`, ownership checks, usable-item registration, and consume-on-use are intentionally disabled.
  {% endstep %}

{% step %}

#### Advanced Framework Detection

* Core adapter settings live under `framework.core`.
* Inventory adapter settings live under `framework.inventory`.
* Each side has its own `mode`, `priority`, and `fallback`.
* Renamed core resources are configured with `framework.core.qbcore.resource`, `framework.core.ox.resource`, or `framework.core.esx.resource`.
* Renamed inventory resources are configured with `framework.inventory.ox_inventory.resource`, `framework.inventory.qb_inventory.resource`, `framework.inventory.qs_inventory.resource`, or `framework.inventory.esx.resource`.
* Custom core behavior uses `framework.core.custom`; custom inventory behavior uses `framework.inventory.custom` and the matching escrow-excluded files.
  {% endstep %}

{% step %}

#### Restrictions & Integrations

* `integrations.disableTarget` calls a configurable targeting export while the flashlight is active.
* `integrations.handcuffCheck.framework` accepts `auto`, `qbcore`, `qbox`, `ox`, `esx`, `statebag`, `export`, or `disabled`.
* In `auto`, the resource checks supported framework metadata and state bags before falling back to the configured export.
* `integrations.notify.mode` accepts `auto`, `ox_lib`, `qbcore`, `chat`, `custom`, or `disabled`.
  {% endstep %}

{% step %}

#### Audio

* `sfx.enabled` is the master sound toggle.
* `sfx.xsound.resource` defaults to `xsound`; `prefer = true` gives it priority when it is started.
* `sfx.interactsound.resource` defaults to `interact-sound`; `prefer = true` gives it priority when it is started.
* `sfx.builtin.resource` defaults to `DaveDev_SFX`; `autoStart = true` starts the fallback when external audio is unavailable.
* `sfx.sounds` controls the clip name, volume, and optional distance for each flashlight action.
* `sfx.dutyBeltModels` controls when holster/unholster sounds are used for configured ped clothing.
  {% endstep %}

{% step %}

#### Light, Controls & Synchronization

* `yawLimit`, `pitchLimit`, `controls`, and `smoothing` control aiming and interpolation.
* `light` and `light.tuning` control beam color, brightness, radius, falloff, distance, and scroll-wheel tuning limits.
* `attach`, `behavior`, and `corona` control prop positioning and the decorative tip glow.
* `net.shareIntervalMs` and `net.maxShareDistance` control remote synchronization frequency and range.
* `evidence` defines helper cone values returned by `GetConeParams()`.
  {% endstep %}
  {% endstepper %}

***

#### <i class="fa-server">:server:</i> Framework and inventory setup

<details>

<summary>Qbox with ox_inventory (recommended Qbox setup)</summary>

Use:

```lua
setup = {
  core = 'qbox',
  inventory = 'ox_inventory',
  itemNames = { 'flashlight' },
  requireItem = true,
  consumeOnUse = false,
}
```

The official Qbox core resource is `qbx_core`. Add the item to ox\_inventory using the ox\_inventory example below.

</details>

<details>

<summary>ox_inventory</summary>

Add an item entry in `ox_inventory/data/items.lua`:

```lua
['flashlight'] = {
  label = 'Flashlight',
  weight = 800,
  stack = false,
  allowArmed = false,
  description = 'A hefty flashlight.',
  client = {
    image = 'flashlight.png',
    export = 'DaveDev_Flashlight.useItem',
  },
  dropModel = 'prop_cs_police_torch',
},
```

Then verify:

* `setup.inventory = 'ox_inventory'` or `auto` resolves to ox\_inventory.
* `setup.itemNames` includes the exact item name.
* `setup.requireItem = true` if the server should verify ownership.

The flashlight does not register ox\_inventory usable items server-side. The item definition's `client.export` calls the flashlight, while the adapter uses ox\_inventory's `Search` export for ownership checks. Configure item consumption through ox\_inventory's own item definition when needed.

</details>

<details>

<summary>QBCore / QB-compatible inventory</summary>

Add the item to your shared item list:

```lua
["flashlight"] = {
  name = "flashlight",
  label = "Flashlight",
  weight = 800,
  type = "item",
  image = "flashlight.png",
  unique = false,
  useable = true,
  shouldClose = true,
  description = "A hefty flashlight."
},
```

Recommended setup:

```lua
setup = {
  core = 'qbcore',
  inventory = 'qb_inventory',
  itemNames = { 'flashlight' },
  requireItem = true,
  consumeOnUse = false,
}
```

The adapter registers `QBCore.Functions.CreateUseableItem` for each configured item name and forwards slot/metadata when enabled.

</details>

<details>

<summary>QS-Inventory</summary>

Add the item to your QS item list and use `setup.inventory = 'qs_inventory'`. The adapter attempts `CreateUsableItem`/`CreateUseableItem`, verifies ownership through the available QS or QB-compatible API, and supports consume-on-use when a compatible removal API is available.

</details>

<details>

<summary>ESX</summary>

Add the item to your ESX item database/list and use:

```lua
setup = {
  core = 'esx',
  inventory = 'esx',
  itemNames = { 'flashlight' },
  requireItem = true,
  consumeOnUse = false,
}
```

The adapter registers `ESX.RegisterUsableItem`, checks inventory counts, and can remove one item when consume-on-use is enabled.

</details>

<details>

<summary>Standalone</summary>

```lua
setup = {
  core = 'standalone',
  inventory = 'standalone',
  itemNames = { 'flashlight' },
  requireItem = false,
  consumeOnUse = false,
}
```

Standalone mode provides commands and exports only. Item checks, usable-item registration, and consume-on-use are disabled.

</details>

<details>

<summary>Custom inventory - trusted bridge (recommended)</summary>

If your inventory already verifies ownership in a server-side usable-item callback, call the trusted export:

```lua
exports['DaveDev_Flashlight']:UseFlashlightTrusted(source, {
  item = itemName,
  slot = slot,
  metadata = metadata,
  framework = 'my_inventory',
})
```

You can also use the configured server-only bridge event:

```lua
TriggerEvent('davedev_flashlight:server:UseTrusted', source, {
  item = itemName,
  slot = slot,
  metadata = metadata,
  framework = 'my_inventory',
})
```

Use `framework/inventory/custom.lua` only when the flashlight itself must register usable items or perform ownership checks. Enable it with `framework.inventory.mode = 'custom'` and `framework.inventory.custom.enabled = true`.

`framework/custom.lua` is the separate custom **core** adapter and does not receive the inventory `api` table.

</details>

***

### <i class="fa-keyboard">:keyboard:</i> Commands, keybinds, and ACE Permissions

* `/flashlight` (equip/holster) and `/flashlight_toggle` (beam on/off) are both configurable.
* Set `commands.equip.requireAce = 'group.admin'` (or any ACE string) to gate the equip command.
* Set `commands.toggleLight.registerKeyMapping = false` if you manage binds in another system.

***

### <i class="fa-clipboard-list-check">:clipboard-list-check:</i> Testing checklist

<details>

<summary>Standalone (Commands)</summary>

Ensure the following:

* `/flashlight` equips&#x20;
* `/flashlight_toggle` flips the beam while equipped (or Middle Mouse Button \[default key])

{% hint style="success" %}
If these work, and there are no errors in your server/client logs, you're good to go!
{% endhint %}

</details>

<details>

<summary>Framework/Inventory (Item)</summary>

Ensure the following:

* Using the configured item calls into the script (Upon item use, the item is equipped).
* It should pass metadata if `metadataPassthrough` is true (e.g. Battery Life, Serial Number, etc.) - (Optional).

{% hint style="success" %}
If these work, and there are no errors in your server/client logs, you're good to go!
{% endhint %}

</details>

<details>

<summary>Implementation / Restraints</summary>

Ensure the following:

* If you set `handcuffCheck` or `disableTarget`, confirm the flashlight works appropriately.

{% hint style="warning" %}
Please note, we do not provide support on external resources, unless the issue is related and caused by our resource.  We can always try to assist you with your integration process, but support for this is not always guaranteed.
{% endhint %}

{% hint style="success" %}
If these work, and there are no errors in your server/client logs, you're good to go!
{% endhint %}

</details>

<details>

<summary>Server/Remote Synchronization</summary>

Ensure the following:

* Another player should see your beam position and on/off state within the `net.maxShareDistance` config.
* If audio is implemented correctly, you should hear the flashlight equip/unequip or turn on/off based on your distance from the player.

{% hint style="success" %}
If these work, and there are no errors in your server/client logs, you're good to go!
{% endhint %}

</details>

***

### <i class="fa-waveform">:waveform:</i> Audio Installation (Next Step)

{% content-ref url="/pages/SPocWOyR5OsSRP8RPSMz" %}
[xsound, Interact-Sound & DaveDev\_SFX](/wiki/immersive-flashlight/info/main-installation/xsound-interact-sound-and-davedev_sfx.md)
{% endcontent-ref %}

***

#### <i class="fa-face-monocle">:face-monocle:</i> Troubleshooting

{% hint style="info" %}
Enable `debugTools.enabled = true`, restart the resource, and run `/flashlight_debug` for adapter, item-name, resource-state, and bridge diagnostics.
{% endhint %}

* **Command exists but nothing happens?** Confirm `commands.equip.enabled = true`. When `setup.requireItem = true`, the command must pass the active inventory adapter's ownership check.
* **Item use does nothing?** Confirm `setup.itemNames` matches the item exactly and that `setup.inventory` resolves to the expected adapter.
* **ox\_inventory item does nothing?** Confirm the item contains `client.export = 'DaveDev_Flashlight.useItem'`.
* **Qbox is not detected?** Confirm the core resource is named `qbx_core` and that the release contains the corrected Qbox resource-name detection.
* **No audio?** Confirm `sfx.enabled = true` and that either `interact-sound` is started or `DaveDev_SFX` is installed/allowed to auto-start.
* **Holster sounds never play?** Add the server's relevant ped/clothing drawables to `sfx.dutyBeltModels`.
* **Standalone ignores requireItem?** This is expected. Standalone inventory mode intentionally disables item checks and consumption.
* **Keybind does not appear?** Check the matching `keybind.enabled` and `registerKeyMapping` settings, then restart the resource and review FiveM key bindings.
