Suty
Shower System

Installation

Installation

1. Drop the resource

Extract suty-shower into resources/[suty]/suty-shower.

2. Ensure dependencies and the resource

server.cfg:

ensure ox_lib
ensure oxmysql
ensure ox_target
ensure ox_inventory
ensure dpclothing
ensure suty-shower

3. Database

Both tables are created automatically on first start. Verify with:

SHOW TABLES LIKE 'player_hygiene';
SHOW TABLES LIKE 'player_dental';

player_hygiene stores body cleanliness, player_dental stores dental hygiene — both keyed by citizenid (VARCHAR(60)).

4. Items

The script uses 4 items. The item names are configurable in config/items.lua and config/dental.lua; the defaults are:

Item Default name Purpose
Soap jabon Required to shower
Deodorant deodorant Slows decay, extends freshness
Perfume perfume Bigger decay slowdown + pheromone effect
Toothbrush + paste toothbrush_paste Brush teeth (dental track)

Pick the snippet that matches your inventory system and drop it in.

Add to ox_inventory/data/items.lua:

["jabon"] = {
    label = "Jabon", weight = 50, stack = true, close = true,
    consume = 1,
    description = "Jabon para ducharte. Usalo cerca de una ducha dentro de tu casa para mantenerte limpio.",
    client = { image = "soap.png", export = "suty-shower.jabon" }
},

["deodorant"] = {
    label = "Desodorante", weight = 100, stack = true, close = true,
    consume = 1,
    description = "Desodorante para mantenerte fresco. Usalo despues de ducharte para que tu higiene dure mas tiempo.",
    client = { image = "deodorant.png", export = "suty-shower.deodorant" }
},

["perfume"] = {
    label = "Perfume", weight = 150, stack = true, close = true,
    consume = 1,
    description = "Perfume de alta calidad. Te mantiene con buen olor por mas tiempo que el desodorante.",
    client = { image = "perfume.png", export = "suty-shower.perfume" }
},

["toothbrush_paste"] = {
    label = "Cepillo y Pasta de Dientes", weight = 100, stack = true, close = true,
    description = "Cepillo con su pasta. Usalo para mantener tu higiene dental al maximo.",
    client = { image = "toothbrush_paste.png", export = "suty-shower.toothbrush_paste" }
},

The client.export field wires each item directly to its suty-shower handler — no manual exports.ox_inventory:registerHook calls required. The consumable items (soap / deodorant / perfume) carry consume = 1 so they're removed on use; the toothbrush is reusable.

5. Choose your HUD mode

Open config/main.luaConfig.HygieneSystem:

  • useCustomPanel = true → the built-in standalone HUD (no qbx_hud needed)
  • useCustomPanel = false → values are forwarded to qbx_hud (hud:client:UpdateHygiene / hud:client:UpdateDental)

If you use the built-in HUD, also set showHUD = true so it appears on screen.

6. 📊 HUD API — use your own HUD

Want to drive a custom HUD (NUI overlay, in-world prop, ESX status, anything)? Turn the built-in panel off and pull values straight from the resource's exports.

First, in config/main.lua:

Config.HygieneSystem.showHUD = false   -- silence the built-in panel

Then read live values from client exports any time you need them:

exports['suty-shower']:GetHygiene()        -- 0-100
exports['suty-shower']:GetDentalHygiene()  -- 0-100
exports['suty-shower']:GetHygieneData()    -- { hygiene, dental, deodorant = { active, secondsLeft }, perfume = { active, secondsLeft } }

Or subscribe to the change event — fires whenever hygiene or dental ticks, and whenever deodorant / perfume start or expire:

AddEventHandler('suty-shower:client:onHygieneChange', function(data)
    -- data = { hygiene, dental, deodorant = { active, secondsLeft }, perfume = { active, secondsLeft } }
    -- redraw your HUD here, push to NUI, update a 3D prop, whatever
end)

The event-driven path is the lightest: zero per-frame work, the resource only sends a payload when something actually changes.

7. Verify

In-game:

/hygiene

You should see a notification with your current Higiene and Dental percentages. Walk up to a shower prop and use the ox_target eye (with soap in your inventory) to test cleaning.

8. (Optional) Discord logging

Open config/discord.lua, set Config.Discord.enabled = true, paste your webhook, and toggle logShower / logStink.