> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shdevelopment.org/llms.txt
> Use this file to discover all available pages before exploring further.

# sh-golf: Interactive Golf Minigame for FiveM

> sh-golf adds a fully playable golf minigame to FiveM. Players swing using an in-game force meter, restricted to the GTA V golf course by default.

sh-golf turns the existing GTA V golf course into a fully playable minigame for your FiveM players. When a player runs the golf command, an in-game swing meter appears — they time and hold their input to set the force of the shot, then watch the ball travel. By default the minigame is restricted to the golf course PolyZone, but you can open it up to the whole map, lock it behind an ACE permission node, or both — all from `config.lua` without touching any encrypted code.

## Dependencies

| Dependency                                      | Required       | Notes                                                  |
| ----------------------------------------------- | -------------- | ------------------------------------------------------ |
| [PolyZone](https://github.com/mkafrin/PolyZone) | ⚠️ Conditional | Required unless `Config.GolfAnywhere = true`           |
| sh-notify                                       | ❌ Optional     | Used when `Config.SHNotify = true`; falls back to chat |

## Commands

| Command      | Description                                                            |
| ------------ | ---------------------------------------------------------------------- |
| `/golf`      | Start the golf minigame (command name is configurable)                 |
| `/propstuck` | Remove any prop stuck to your character (command name is configurable) |

## Configuration

All options are set in `config.lua`. The file is straightforward — every value is a single line with no nested tables.

```lua config.lua theme={null}
Config.GolfCommand    = 'golf'     -- The command players type to start golfing
Config.GolfAnywhere   = false      -- true = removes the PolyZone restriction entirely
Config.PermRestrict   = false      -- true = requires ACE permission to use /golf
Config.PermName       = 'golf'     -- The ACE node name checked when PermRestrict = true
Config.SHNotify       = true       -- true = sh-notify, false = fallback to chat message

Config.DefaultForce         = 10.0  -- Starting position of the force meter on the swing UI
Config.BallMarkerDistance   = 200   -- Distance (units) at which the ball marker renders
Config.BallDeleteDistance   = 200   -- Distance (units) at which the ball prop despawns
Config.PropCommand          = true  -- Enable or disable the /propstuck command
Config.PropStuckCommand     = 'propstuck'  -- Command name for the prop cleanup
```

<Tip>
  Set `Config.GolfAnywhere = true` to let players bring clubs anywhere on the map — great for custom golf course MLOs that aren't in the default PolyZone boundary.
</Tip>

## ACE Permission Setup

If you want to restrict golfing to certain player groups (for example, VIP members), enable the permission gate and add the appropriate ACE entries to your `server.cfg`.

<Steps>
  <Step title="Enable permission restriction">
    In `config.lua`, set `Config.PermRestrict = true` and choose a permission node name via `Config.PermName`.
  </Step>

  <Step title="Grant the ACE to a group">
    Add the allow rule in `server.cfg`, replacing `vip` with the group you want to grant access:

    ```cfg server.cfg theme={null}
    add_ace group.vip golf allow
    ```
  </Step>

  <Step title="Assign players to the group">
    Add players to the group using their licence identifier:

    ```cfg server.cfg theme={null}
    add_principal identifier.license:XXXXXXXXXXXXXXX group.vip
    ```
  </Step>
</Steps>

<Note>
  Players without the ACE permission receive a notification when they attempt to use `/golf` and the command does nothing. No errors are thrown server-side.
</Note>

## Customising the Golf Zone

The PolyZone boundary that defines the allowed golf area is stored in `locations.lua`. This file is **escrow-ignored**, so you can edit it freely without breaking the resource's encrypted code.

Open `locations.lua` and replace the existing `vector2` coordinate list with one that matches your custom golf course boundary. Each coordinate is a corner point of the polygon that outlines the playable area.

```lua locations.lua theme={null}
Config.GolfZones = {
    [1] = {
        points = {
            vector2(918.0, -1630.0),
            vector2(1000.0, -1600.0),
            vector2(1050.0, -1700.0),
            -- Add as many points as needed to trace your course boundary
            vector2(920.0, -1750.0),
        },
        minZ = 35.0,
        maxZ = 70.0,
        box  = false,
    },
}
```

<Warning>
  Do **not** rename the resource folder. sh-golf validates its own resource name at startup and will immediately stop itself if the name does not match `sh-golf`. Keep the folder name exactly as it was when you downloaded it.
</Warning>
