# :lipstick: Makeup
Documentation relating to the **jo_hairdresser_makeup** add-on for the [Hairdresser script](hairdresser).

:::: tabs
::: tab BUY
[Buy the add-on](https://jumpon-studios.com/redm/makeup)
:::

::: tab PREVIEW
<iframe width="560" height="315" src="https://www.youtube.com/embed/ybDiAx_a-1s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
:::
::::

## 1. Installation
::: warning
The [Hairdresser script](hairdresser) is required to use this add-on.
:::

To install jo_hairdresser_makeup:
- Drag and drop the resource into your resources folder
  - jo_hairdresser_makeup
- Add this ensure to your server.cfg after `ensure jo_hairdresser`
  - `ensure jo_hairdresser_makeup`

Congratulations, the **Makeup** add-on is ready to use!

## 2. Usage

:::: tabs
::: tab Open makeup
Go to a hairdresser and open the hairdresser menu.

When the add-on is enabled, two new entries can appear in the native hairdresser menu:
- **Makeup**
- **Lifestyle**
:::

::: tab Makeup features
In the makeup menu, you can:
- **Foundation** - Select a foundation variation, opacity, and colors
- **Blusher** - Select a blush variation, opacity, and color
- **Eyeshadow** - Select an eyeshadow variation, opacity, and colors
- **Eyeliner** - Select an eyeliner variation, opacity, and color
- **Lipstick** - Select a lipstick variation, opacity, and colors

Changes are previewed on the player before purchase.
:::

::: tab Lifestyle features
In the lifestyle menu, you can edit:
- **Ageing**
- **Acne**
- **Scar**
- **Complexion**
- **Skin mottling**
- **Freckles**
- **Moles**
- **Spots**

Each category supports previewing and saving through the Hairdresser purchase flow.
:::

::: tab Purchase flow
The add-on uses the Hairdresser menu prompts and purchase feedback.

When multiple payment options are available, players can switch between them before buying. Removing a makeup or lifestyle overlay is free.
:::
::::

## 3. Configuration
The configuration files are located in the `config` folder within the resource. This folder contains two subfolders:

- **`_default.lock/`** - Contains the default configuration files. **Do not edit these files directly** as they may be overwritten during updates.
- **`custom/`** - This is where you place your custom configuration files to override the defaults.

### How to customize the configuration

1. Navigate to `jo_hairdresser_makeup/config/_default.lock/`
2. Copy the file you want to modify (e.g., `prices.lua`)
3. Paste it into `jo_hairdresser_makeup/config/custom/`
4. Edit the copied file in the `custom` folder

The script automatically loads files from `custom/` first, and only uses `_default.lock/` as a fallback. This system ensures your customizations are preserved when updating the script.

### Default configuration files

`jo_hairdresser_makeup/config/_default.lock/global.lua`

```lua
Config.makeup = true    -- Enable or disable the "makeup" menu
Config.lifestyle = true -- Enable or disable the "lifestyle" menu
```

`jo_hairdresser_makeup/config/_default.lock/lang.lua`

```lua
Lang.makeup = "Makeup"
Lang.lifestyle = "Lifestyle"
Lang.noMoney = "You don't have enough money"
Lang.noGold = "You don't have enough gold"
Lang.color1 = "Color"
Lang.color2 = "Color"
Lang.color3 = "Color"
-------------
-- MAKE-UP
-------------
Lang.makeupDesc = "Custom your makeup"
Lang.blendedFlick = "Blended Flick"
Lang.blusher = "Blusher"
Lang.border = "Border"
Lang.contoured = "Contoured"
Lang.curved = "Curved"
Lang.double = "Double"
Lang.doubleTop = "Double Top"
Lang.drama = "Drama"
Lang.egyptian = "Egyptian"
Lang.eyeliner = "Eyeliner"
Lang.eyeshadow = "Eyeshadow"
Lang.eyeshadowColor = "Eyeshadow Color"
Lang.facePowder = "Face Powder"
Lang.faint = "Faint"
Lang.flushed = "Flushed"
Lang.foundation = "Foundation"
Lang.foundationColor = "Foundation Color"
Lang.fulled = "Fulled"
Lang.heart = "Heart"
Lang.heavyWing = "Heavy Wing"
Lang.highbrow = "Highbrow"
Lang.highlighted = "Highlighted"
Lang.hooked = "Hooked"
Lang.indian = "Indian"
Lang.indianBold = "Indian Bold"
Lang.indianFull = "Indian full"
Lang.lined = "Lined"
Lang.lipstick = "Lipstick"
Lang.lipstickColor = "Liptstick Color"
Lang.long = "Long"
Lang.makeup = "Makeup"
Lang.matte = "Matte"
Lang.neatArc = "Neat Arc"
Lang.none = "None"
Lang.pinup = "Pin-up"
Lang.pinupBold = "Pin-up Bold"
Lang.rosy = "Rosy"
Lang.shadow = "Shadow"
Lang.simple = "Simple"
Lang.smokyEye = "Smoky Eye"
Lang.smudged = "Smudged"
Lang.square = "Square"
Lang.strong = "Strong"
Lang.twotoneWing = "Two-tone Wing"
Lang.underlined = "Underlined"
Lang.winged = "Winged"
-------------
-- LIFESTYLE
-------------
Lang.lifestyleDesc = "Custom your lifestyle"
Lang.acne = "Acne"
Lang.ageing = "Ageing"
Lang.ageing_var0 = "Variation 1"
Lang.ageing_var1 = "Variation 2"
Lang.ageing_var2 = "Variation 3"
Lang.ageing_var3 = "Variation 4"
Lang.ageing_var4 = "Variation 5"
Lang.ageing_var5 = "Variation 6"
Lang.ageing_var6 = "Variation 7"
Lang.ageing_var7 = "Variation 8"
Lang.ageing_var8 = "Variation 9"
Lang.ageing_var9 = "Variation 10"
Lang.ageing_var10 = "Variation 11"
Lang.ageing_var11 = "Variation 12"
Lang.ageing_var12 = "Variation 13"
Lang.ageing_var13 = "Variation 14"
Lang.ageing_var14 = "Variation 15"
Lang.ageing_var15 = "Variation 16"
Lang.ageing_var17 = "Variation 17"
Lang.ageing_var18 = "Variation 18"
Lang.ageing_var19 = "Variation 19"
Lang.ageing_var20 = "Variation 20"
Lang.ageing_var21 = "Variation 21"
Lang.ageing_var22 = "Variation 22"
Lang.ageing_var23 = "Variation 23"
Lang.alcoholic = "Alcoholic"
Lang.bigCheeked = "Big Cheeked"
Lang.blemished = "Blemished"
Lang.blemishes = "Blemishes"
Lang.blotched = "Blotched"
Lang.broken = "Broken"
Lang.bunch = "Bunch"
Lang.cast = "Cast"
Lang.chapped = "Chapped"
Lang.cheeked = "Cheeked"
Lang.cheeky = "Cheeky"
Lang.clawed = "Clawed"
Lang.coarse = "Coarse"
Lang.complexion = "Complexion"
Lang.constant = "Constant"
Lang.covered = "Covered"
Lang.cracked = "Cracked"
Lang.damaged = "Damaged"
Lang.dappled = "Dappled"
Lang.dotted = "Dotted"
Lang.dwindling = "Dwindling"
Lang.exhausted = "Exhausted"
Lang.faded = "Faded"
Lang.fatigued = "Fatigued"
Lang.few = "Few"
Lang.flecked = "Flecked"
Lang.flicked = "Flicked"
Lang.flushed = "Flushed"
Lang.freckles = "Freckles"
Lang.grime = "Grime"
Lang.group = "Group"
Lang.hacked = "Hacked"
Lang.healthyGlow = "Healthy Glow"
Lang.hearty = "Hearty"
Lang.lifestyle = "Lifestyle"
Lang.lighted = "Lighted"
Lang.marred = "Marred"
Lang.minor = "Minor"
Lang.moles = "Moles"
Lang.motley = "Motley"
Lang.nosy = "Nosy"
Lang.odd = "Odd"
Lang.patched = "Patched"
Lang.patchy = "Patchy"
Lang.peppered = "Peppered"
Lang.pinpricked = "Pinpricked"
Lang.pronounced = "Pronounced"
Lang.raised = "Raised"
Lang.random = "Random"
Lang.reddening = "Reddening"
Lang.ruddy = "Ruddy"
Lang.rugged = "Rugged"
Lang.scalped = "Scalped"
Lang.scar = "Scar"
Lang.scarce = "Scarce"
Lang.scattered = "Scattered"
Lang.scraped = "Scraped"
Lang.set = "Set"
Lang.several = "Several"
Lang.skinMottling = "Skin Mottling"
Lang.slashed = "Slashed"
Lang.sliced = "Sliced"
Lang.smashed = "Smashed"
Lang.sparse = "Sparse"
Lang.speckled = "Speckled"
Lang.split = "Split"
Lang.spots = "Spots"
Lang.spots_var0 = "Variation 1"
Lang.spots_var1 = "Variation 2"
Lang.spots_var2 = "Variation 3"
Lang.spots_var3 = "Variation 4"
Lang.spots_var4 = "Variation 5"
Lang.spots_var5 = "Variation 6"
Lang.spots_var6 = "Variation 7"
Lang.spots_var7 = "Variation 8"
Lang.spots_var8 = "Variation 9"
Lang.spots_var9 = "Variation 10"
Lang.spots_var10 = "Variation 11"
Lang.spots_var11 = "Variation 12"
Lang.spots_var12 = "Variation 13"
Lang.spots_var13 = "Variation 14"
Lang.spots_var14 = "Variation 15"
Lang.spots_var15 = "Variation 16"
Lang.spotted = "Spotted"
Lang.spread = "Spread"
Lang.stippled = "Stippled"
Lang.strewn = "Strewn"
Lang.struck = "Struck"
Lang.styppled = "Styppled"
Lang.sunBurnt = "Sun Burnt"
Lang.sunned = "Sunned"
Lang.torn = "Torn"
Lang.toughened = "Toughened"
Lang.uneven = "Uneven"
Lang.varied = "Varied"
Lang.visually = "Visually"
Lang.weathered = "Weathered"
Lang.windWhipped = "Wind-whipped"
```

`jo_hairdresser_makeup/config/_default.lock/prices.lua`

```lua
-- ================================================================
-- PRICE CONFIGURATION GUIDE
-- ================================================================
-- Need to build or adjust a price table quickly?
-- Use the official Price Generator here:
--   https://docs.jumpon-studios.com/DeveloperResources/price-generator
--
-- The generator creates ready-to-paste Lua price tables for this config.
-- Copy the generated Lua code and paste it as the value of the relevant
-- price entry or model override.
-- ================================================================

Config.prices = {
    foundation = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    blush = {
        operator = "or",
        { money = 2 },
        { gold = 1 },
    },
    eyeshadow = {
        operator = "or",
        { money = 3 },
        { gold = 1 },
    },
    eyeliner = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    lipstick = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    ageing = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    acne = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    scar = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    complex = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    disc = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    freckles = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    moles = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
    spots = {
        operator = "or",
        { money = 1 },
        { gold = 1 },
    },
}

-- You can disable a category entirely by setting it's price to -1 :
-- Config.prices.foundation = -1
```

## 4. For developers

### Actions

Actions are one of the two types of Hooks. They provide a way to run a function at a specific point in the execution of scripts. Callback functions for an Action do not return anything back to the calling Action hook. They are the counterpart to Filters.

Below is the available action in the jo_hairdresser_makeup script.

#### `[Client]` Init
Triggered when the add-on links to jo_hairdresser and registers its Hairdresser menu entries.

```lua
exports.jo_hairdresser_makeup:registerAction('init', function()
    -- Your code here
end)
```

### Filters

[Filters](/DeveloperResources/filters) allow you to modify data or permissions synchronously at specific points in the script. Below is the complete list of `jo_hairdresser_makeup` filters and how to use them.

#### `[Client]` Can open makeup menu
Control whether the Makeup entry is added to the Hairdresser menu.

```lua
-- @param canOpen - boolean (default true)
exports.jo_hairdresser_makeup:registerFilter('canOpenMakeupMenu', function(canOpen)
	return canOpen
end)
```

#### `[Client]` Can open lifestyle menu
Control whether the Lifestyle entry is added to the Hairdresser menu.

```lua
-- @param canOpen - boolean (default true)
exports.jo_hairdresser_makeup:registerFilter('canOpenLifestyleMenu', function(canOpen)
	return canOpen
end)
```

#### `[Server]` Can buy
Control whether the purchase can continue before money is charged.

```lua
-- @param canBuy - boolean (default true)
-- @param source - serverID of the player
-- @param currentData - table: purchase data
-- @param moneyType - any: selected money type/payment context
exports.jo_hairdresser_makeup:registerFilter('canBuy', function(canBuy, source, currentData, moneyType)
	return canBuy
end)
```
