# Storage Lockers

## Introduction

Storage lockers will add the ability for players to buy their own storage lockers which are locked by a personal customizable pin.

**This script is written to work with** [**QBCore**](https://qbcore-framework.github.io/qb-docs/) **and** [**Zap Hosting ESX Pack**](https://github.com/zaphosting/esx_12)

**This resource requires** [**QB-Menu** ](https://github.com/qbcore-framework/qb-menu)**or ESX Menu Default**

{% hint style="info" %}
**This is compatible with the following inventory systems:**

* [qb-inventory](https://github.com/qbcore-framework/qb-inventory/) (QBCore)
* [lj-inventory](https://github.com/loljoshie/lj-inventory) (QBCore)
* [ox\_inventory](https://github.com/overextended/ox_inventory) (QBCore/ESX)
* [chezza-inventory](https://forum.cfx.re/t/paid-release-chezzas-inventory-esx/2040417) (ESX)
  {% endhint %}

Features of Storage Lockers:

* Unlimited Storage Lockers.
* Lockers can be created/deleted by either staff only or by jobs (editable in config)
* Lockers can be set as Objects which will automatically be created by the script.
* Any GTA Object can be used as a locker object, just specify on locker command.
* Lockers have individual prices storage amounts and slots.
* Lockers accessible by anyone who knows the locker pin code.
* Configurable Blips for available lockers and blips to see the players owned lockers
* Ability for Police to Raid Lockers (Item Requirement can be set in config, can be set to any item.)
* Players can sell their locker for a partial or full refund (editable in config)

***

## Installation

* Download the power\_storageLocker from Keymaster
* Run the .sql file in your database.
* Add the files to your resources folder
* Ensure that the resource file will start (either ensure your resource in the server.cfg or inside a folder which is started on server start)
* Edit the config file to your needs
* Restart your server

***

## Configuration

Select the tab below for your framework to see the configuration options available.

{% tabs %}
{% tab title="Framework Options" %}

```lua
-- Enable Support for QBCore 
enableQBCore = true

QBCoreResourceName = 'qb-core'

-- This supports the following resources: qb-invemtory, lj-inventory, ox_inventory
QBInventory = 'qb-inventory'

-- Enable Target Supprt, Supports QB-Target and OX_Target
enableTarget = true

-- Enable Support for ESX 
enableESX = false

-- ESX Inventory 
-- Compatible with 'ox_inventory' and 'chezza-inventory' and 'mf_inventory'
esxInventory = 'ox_inventory'

-- The position of the menu of the esx menu.
esxMenuPosition = 'top-right'

```

{% endtab %}

{% tab title="Configuration Options" %}
Command Settings

```lua
-- The command that is used to create a new locker.
addLockerCommand = 'addlocker'

-- The command that is used to delete a locker.
deleteLockerCommand = 'deletelocker'

-- This will allow only staff to add/delete lockers, if this is disabled then it will use the job whitleist below.
addLockerStaffOnly = true 

-- The jobs required to use the add/delete locker command, if the staff only setting is disabled.
addLockerJobs = {
 ['realestate'] = {2, 3, 4}, -- This will only allow rel estate agents with grade 2, 3 or 4.
 ['realestateagent'] = {1, 2, 3}, 
}
```

Item Settings

```lua
-- This allows an item to be used by anyone to create a storage locker.
useItems = true

-- The name of the items that can be used to create storage lockers
-- supplied in format of, item name, object name, storage amount, storage slots.
itemNames = {
 {name = 'small_safe', object = 'prop_ld_int_safe_01', storage = 200000, slots = 30},
 {name = 'medium_safe', object = 'p_v_43_safe_s', storage = 30000, slots = 75},
 {name = 'large_safe', object = 'h4_prop_h4_safe_01a', storage = 500000, slots = 125},
 {name = 'container', object = 'tr_prop_tr_container_01a', storage = 1000000, slots = 250},
}

-- Should the item be removed on use.
removeItemOnUse = true
```

Raid Settings

```lua
-- The jobs required to raid storage lockers. 
raidJobs = {
 'police',
}

-- This will allow only raid jobs with an item to raid lockers. 
raidItemRequired = false 

-- This is the name of the item required to raid lockers.
raidItemName = 'police_stormram'
```

Locker Settings

```lua
-- This will enable a DrawMarker at the closest locker.
enableMarker = true 

-- This allows only the owner to sell the locker.
ownerOnlySale = true 

-- This defines the amount to give players when they sell the locker.
salePercentage = 0.90 -- (Default: 90%) (Example: 0.50 = 50%)

-- This allows only the owner to change the locker pin.
ownerOnlyPinChange = true 

objectDistance = 2.75 -- This is the distance to the locker object before the prompt is shown.
promptDistance = 1.5 -- This is the distance to the locker before the prompt is shown (this is used on lockers that do not have an object).
```

Blip Settings

```lua
-- This will show unowned locker blips.
enableUnownedBlips = false 

unownedBlip_Color = 5
unownedBlip_Sprite = 40
unownedBlip_Scale = 0.6

-- This will show locker blips to the player that owns the unit.
enableOwnedBlips = true 

ownedBlip_Color = 2
ownedBlip_Sprite = 40
ownedBlip_Scale = 0.6
```

{% endtab %}

{% tab title="Language" %}
In this section you can edit the language if you need to translate to another language or edit the wording.

```lua
Lang = {
 -- Prompt 
 ['accessLocker'] = "~w~Press ~g~E~w~ To Access Storage Locker",
 ['placeLocker'] = "~w~Press ~g~E~w~ To Place Locker",

 -- Blip Name
 ['blipName'] = "Storage Locker",

 -- Menu Options
 ['menuHeader'] = "Storage Locker",
 ['purchaseLocker'] = "Purchase Locker",
 ['purchaseLockerDesc'] = "Buy This Locker for $",
 ['closeMenu'] = "Close",
 ['raidLocker'] = "Raid Locker",
 ['enterPin'] = "Enter Pin",
 ['raidLockerDesc'] = "Requires a warrant",
 ['openLocker'] = "Open Locker",
 ['openLockerDesc'] = "View the Locker Inventory",
 ['changePin'] = "Change Pin",
 ['sellLocker'] = "Sell Locker",
 ['lockerInfo'] = 'Weight: %s | Slots: %s | Price: $%s',

 -- Notifications
 ['pinChanged'] = {message = "Your pin has been changed.", type = "success"},
 ['lockerCreated'] = {message = "Storage Locker Created.", type = "success"},
 ['lockerDeleted'] = {message = "Storage Locker Deleted.", type = "success"},
 ['lockerPurchased'] = {message = "Storage Locker Purchased, The Pin is 1234.", type = "success"},
 ['lockerSold'] = {message = "Storage Locker Sold, You have been refunded $", type = "success"},
 ['newPin'] = {message = "Insert your new pin, Maximum of 8 Numbers.", type = "success"},
 ['wrongArgs'] = {message = "Usage /"..addLockerCommand.." [Price] [Storage Amount] [Storage Slots] [Create Object (0/1)] [Object Name (prop_container_05mb)]", type = "error"},
 ['wrongJobGrade'] = {message = "You do not have the correct job grade.", type = "error"},
 ['wrongJob'] = {message = "You do not have the correct job.", type = "error"},
 ['notEnoughMoney'] = {message = "Not Enough Money.", type = "error"},
 ['ownerOnlySale'] = {message = "Only the owner can sell the locker.", type = "error"},
 ['ownerOnlyPin'] = {message = "Only the owner can change the Pin.", type = "error"},
 ['noRequiredItem'] = {message = "You do not have the required item.", type = "error"},
 ['incorrectPin'] = {message = "Incorrect Pin", type = "error"},
}
```

{% endtab %}
{% endtabs %}

***

## Editable files

### client.lua

#### Custom Notifications

If you would like to edit the notifications to add your own custom notifications or to match them to your other server notifications, you can edit them in the client.lua file. Default notifications are as follows:

```lua
-- You can change the notification here.
RegisterNetEvent('power:locker:notification')
AddEventHandler('power:locker:notification', function(message, type)
 if enableQBCore then 
  TriggerEvent('QBCore:Notify', message, type)
 end 

 if enableESX then 
  TriggerEvent('chat:addMessage', {color = {255, 255, 255}, args = {"^8Warehouse", message}})
 end 
end)
```

#### Inventory triggers

```lua
function openStorageInventory(storageId, storage, slots) 
 if enableQBCore then 
  if QBInventory == 'ox_inventory' then 
   exports.ox_inventory:openInventory('stash', {id = storageId, owner = false, slots = tonumber(slots), weight = tonumber(storage)})
  else 
   TriggerServerEvent("inventory:server:OpenInventory", "stash", storageId, {maxweight = tonumber(storage), slots = tonumber(slots)})
   TriggerEvent("inventory:client:SetCurrentStash", storageId)
  end 
 end

 if enableESX then 
  if esxInventory == 'ox_inventory' then 
   exports.ox_inventory:openInventory('stash', {id = storageId, slots = tonumber(slots), weight = tonumber(storage)})
  end 

  if esxInventory == 'mf-inventory' then 
   exports["mf-inventory"]:openOtherInventory(storageId)
  end 

  if esxInventory == 'chezza-inventory' then 
   TriggerEvent('inventory:openInventory', {type = "stash", id = storageId, title = "Storage Locker", weight = tonumber(storage), delay = 0, save = true})
  end 

  if esxInventory == 'quasar-inventory' then 
   local other = {}
   other.maxweight = tonumber(storage)
   other.slots = tonumber(80) 
   TriggerServerEvent("inventory:server:OpenInventory", "stash", storageId, other)
   TriggerEvent("inventory:client:SetCurrentStash", storageId)
  end 
 end 
end
```

### HTML

#### HTML files are able to be edited.

* index.html
  * Additional language translations can be edited here listed as:
    * <pre><code><strong>Locker Creation
      </strong><strong>Locker Price
      </strong><strong>Storage Amount
      </strong><strong>Storage Slots
      </strong><strong>Create Object Locker
      </strong><strong>Yes
      </strong><strong>No
      </strong><strong>Create Object Locker
      </strong><strong>Create Locker
      </strong><strong>Enter Pin
      </strong></code></pre>
* script.js
* style.css

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.power-scripts.com/storage-lockers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
