# mack-xxx
Clip : https://medal.tv/games/red-dead-2/clips/nEJ87gC4jFw4SisgR?invite=cr-MSxycnksMTkxMDIwMzU5
Adult scenes for RedM (RSG Core + ox_lib). This is the adult-only sibling of `mack-emotes-advanced`:
it has the `/whore` and `/sex` scenes, the bed raycasting and the bed props, and nothing else (no emotes, sit, lean, lay or sleep).
**18+ content.** Do not start this resource on a server that does not allow it. There is no master switch in the config:
the resource itself is the switch (do not `ensure` it where you do not want it). If you sell or distribute it, check the
content rules of your platform (Tebex, Cfx.re) first.
## Requirements
- `rsg-core`
- `ox_lib`
- **OneSync** enabled (the server checks player positions: distance between players, distance to the bed)
- For the "naked" option only: `rsg-clothes` and `rsg-appearance` (without them the player is simply not undressed)
## Install
1. Put the `mack-xxx` folder in your resources folder.
2. Add `ensure mack-xxx` to `server.cfg` after `rsg-core` and `ox_lib`.
3. Restart the server.
## Commands
- `/whore` - an NPC companion on the nearest bed. You confirm and pay, then are asked for a male or female companion, then
naked or clothed. Closing any of the questions cancels everything and nothing is charged.
- `/sex [id]` - a scene between two players on a bed. The other player is asked and has to accept. The server checks the
genders (one male, one female), the distance between the players and to the bed, the cooldown and that the bed is free.
- `/stopscene` - ends the scene you are in. BACKSPACE does the same.
- `/sextest [male|female] [naked]` - the `/sex` scene alone with an NPC partner, for tuning. Off by default
(`Config.Adult.SoloTest.Enabled`) and **restricted**: only players with the ACE permission `command.sextest` can run it.
Turn it off again on a live server.
During a scene: BACKSPACE stops, ENTER changes position, SPACE changes the camera angle.
All commands can be renamed in `Config.Commands`.
## Beds
A scene starts on the nearest known bed prop (`props.lua`: beds and bedrolls only). If there is none, a raycast looks
for a bed-shaped surface in front of you (beds that are part of the map). Tables, desks, counters, benches, couches and
wagons are rejected (the name list is at the bottom of `props.lua`).
Tune it in `Config.BedFallback` (`MinHeight`, `MaxHeight`, `MinLength`, `RejectObjects`, `AllowZones`, `HeadingOffset`).
Set `Config.Debug = true` to draw a red marker on the scene anchor while a scene runs.
Two players cannot take the same bed: the server holds a claim for every bed in use, for `/whore` and for `/sex`.
A claim ends with the scene, when its owner walks away from it, or after the scene time limit, so a crashed client can
never block a bed for good.
## Settings (config.lua)
- `Config.Adult.Price`, `PayForService`, `RefundWindow`, `WhoreRequiresMale`, `Cooldown`, `Timer`, `MaxPlayerDistance`, `RequestTimeout`
- `Config.Adult.GenderValues` - what `charinfo.gender` values mean male / female (rsg-core default: male `0`, female `1`)
- `Config.Adult.NpcModels` (clothed female), `NpcModelsMale` (clothed male)
- `Config.Adult.WhoreOptions` - `AskGender`, `DefaultGender`, `AskNaked`, `NakedNpcModels`
- `Config.Adult.Naked` - `Enabled`, `Categories` (what gets removed), `RestoreEvent` (for other clothing scripts)
- `Config.Adult.Stress` - stress relief afterwards (see below)
- `Config.Adult.Scenes`, `AnchorZOffset`, `Tune` - positions and live tuning
- `Config.Adult.Camera`, `Help` - camera angles and the on-screen key help
- `Config.Weapons` - holster the weapon during a scene, and keep it holstered
- `Config.Watchdog` - a scene ends when you are put on a mount or in a vehicle, handcuffed, or flagged dead
(`Enabled = false` switches these checks off; a drawn weapon is still put away if `Config.Weapons.BlockDraw` is on)
- `Config.Blockers` - swimming / falling / ragdoll can stop a scene from starting
- `Config.Seats` - the server-held bed claims
- `Config.Commands` - rename the commands
- `Config.Locale` and `locales/en.json` - texts
## Stress relief
Stress relief is done by the **server**, never by the client: when a scene that the server saw running for at least
`Config.Adult.Stress.MinDuration` seconds ends, the server lowers the character's `stress` metadata by `Amount` and
then sends `UpdateEvent` to that player so the HUD refreshes (default `hud:client:UpdateStress`; set it to `nil` if your
HUD does not need it). **Upgrade note:** the old `Config.Adult.Stress.Event` (a server event triggered by the client) no
longer exists; remove it from a customised config.
## Naked option
Before undressing, the outfit is read from `rsg-clothes`. It is put back when the scene ends: stop, death, a forced stop
or a resource restart. If the clothes cannot be restored safely (resource missing, no body parts available) the player
is **not** undressed and is told so; the scene still runs. If you use another clothing script, set
`Config.Adult.Naked.RestoreEvent` to a client event that dresses the player again.
The animation has one male and one female clip. The companion always plays the clip of the role opposite to the player's
gender, whatever its model looks like.
## Security notes
What the server enforces:
- `/sex`: both players online, not busy, not on cooldown, not dead / handcuffed / in jail, one male and one female
character, close to each other and close to the bed (checked again when the answer is accepted), bed free.
The other player must accept. One open request per player, and requests are rate limited.
- `/whore`: payment is taken on the server (cash, price, cooldown, gender rule). The refund after a failed start is only
possible once, within `RefundWindow` seconds, and never after the scene was confirmed as started.
- Scene changes (ENTER) are validated (scene index in range) and rate limited. A player can only end a scene that is
really shared with them.
- Scenes that are never reported as ended by their client are dropped by the server after `Timer` + 30 seconds.
- Stress relief is applied by the server. Character names shown in the request dialog are stripped of markup.
Known limits (they apply to any client side animation script):
- The animation, the NPC and the bed detection run on the client. A player with a cheat tool can play the NPC animation
without paying; the payment cannot be made unbreakable. Treat the price as an in-character toll, not as a security
feature, and keep an eye on your server's anticheat.
- The server cannot check that the position sent by `/sex` is really a bed, only that both players stand next to it.
- NPC companions are networked peds created by the player; if the player's game crashes during a scene the ped is
removed by OneSync when the owner leaves, but a server-wide ped cleanup is a good safety net.
## Escrow
`fxmanifest.lua` is prepared for Cfx.re Asset Escrow (`lua54 'yes'`, every script declared, no `load()` / `io.*`).
`client.lua` and `server.lua` are protected; `config.lua`, `props.lua` and `locales/*.json` stay editable by the buyer
(`escrow_ignore`). `rsg-clothes` and `rsg-appearance` are optional and are therefore not in `dependencies`.
## Events
Everything this resource sends is prefixed `mack-xxx:`, so it can run next to `mack-emotes-advanced` without clashing.
Do not run both with the same command names: if both are started, change `Config.Commands` in one of them.
These events are internal (client to server and back); do not trigger them from other resources.
## Changelog
- **1.1.0** - Security and bug-fix pass: server side stress relief, bed claims for `/sex`, claim time limit and position
check, refund window, scene validation and rate limits, dead / handcuffed / jailed checks on the server, `/sextest`
restricted, stale scene cleanup, `Config.Watchdog.Enabled` now respected, safer return from the bed, re-check after the
`/whore` dialogs, camera angle guard.
- **1.0.0** - First release.