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

# Developer reference

> Extend the DD Gamemaster context menu with your own actions, providers, and default items

Use `config/contextMenus.lua` to configure weapons, animations, and a registry-based context menu system that lets you add your own actions and providers without editing client code.

## Registry-based menu system

The menu is powered by a lightweight registry available at runtime via `GM.ContextMenu`:

* **Actions**: `registerAction(id, handler)` maps a menu `id` to a function.
* **Prefix actions**: `registerActionPrefix(prefix, handler)` handles any id starting with the prefix.
* **Providers**: `register(providerFn)` returns a list of items for the current click context (ground, ped, vehicle, selection).
* **Default items**: Always-visible items can be added statically with `Config.ContextMenuDefaultItems`, or dynamically at runtime.

Handlers receive `(data, meta)`. `meta.actionId` is the clicked id; `meta.context` mirrors build-time context and can include `ground`, `selectionCount`, `targetPed`, `targetVehicle`.

### Example: register actions and a provider

```lua config/contextMenus.lua theme={null}
-- Wait until the context menu registry is ready
CreateThread(function()
  while not (GM and GM.ContextMenu and GM.ContextMenu.registerAction) do
    Wait(50)
  end
  local CM = GM.ContextMenu

  -- Stop all selected peds (no extra data required)
  CM.registerAction('example_stop_selected', function(_, _)
    if not (GM and GM.State and GM.State.selection) then return end
    for _, ent in ipairs(GM.State.selection) do
      if DoesEntityExist(ent) and IsEntityAPed(ent) then
        if ClearPedTasks then ClearPedTasks(ent) end
        if TaskStandStill then TaskStandStill(ent, -1) end
      end
    end
  end)

  -- Move selection to your last right-clicked ground position
  CM.registerAction('example_goto_last_click', function(_, meta)
    local ctx = meta and meta.context
    if ctx and ctx.ground and GM and GM.Commands then
      GM.Commands.goToDirect(ctx.ground)
    end
  end)

  -- Provider: show a hello action when hovering a ped
  CM.register(function(ctx)
    local items = {}
    if ctx and ctx.targetPed and IsEntityAPed(ctx.targetPed) then
      items[#items + 1] = { id = 'example_stop_selected', label = 'Stop Selected', data = {} }
    end
    return items
  end)
end)
```

### Hello world: your first custom action and provider

This is the smallest end-to-end example. It registers a new action that prints a message using `Bridge.Debug`, and a provider that shows the item when you right-click on a ped.

```lua config/contextMenus.lua theme={null}
-- 1) Register the action (what happens when clicked)
CreateThread(function()
  while not (GM and GM.ContextMenu and GM.ContextMenu.registerAction) do Wait(50) end
  local CM = GM.ContextMenu

  CM.registerAction('example_hello_world', function(data, _)
    local msg = (data and data.message) or 'Hello from Context Menu!'
    if Bridge and Bridge.Debug then
      Bridge.Debug('[GM] ' .. tostring(msg))
    end
  end)

  -- 2) Provide the item (when and where it appears)
  CM.register(function(ctx)
    local items = {}
    if ctx and ctx.targetPed and IsEntityAPed(ctx.targetPed) then
      items[#items + 1] = {
        id = 'example_hello_world',
        label = 'Hello World',
        data = { message = 'Howdy!' }
      }
    end
    return items
  end)
end)
```

<Note>
  If you want your hello world to always be visible, add it as a default item instead:

  ```lua config/contextMenus.lua theme={null}
  Config.ContextMenuDefaultItems = {
    { id = 'example_hello_world', label = 'Hello World', data = { message = 'Always visible' } },
  }
  ```
</Note>

### Providers explained for beginners

* **Think of a provider as a menu generator.** It runs each time you open the menu and returns a list of items that make sense for the current situation.
* **The `ctx` (context) tells you what the player pointed at:**
  * `ctx.ground`: where the right-click happened (a `vector3`)
  * `ctx.selectionCount`: how many entities are currently selected
  * `ctx.targetPed`: the ped under the cursor, if any
  * `ctx.targetVehicle`: the vehicle under the cursor, if any
* **Return an array of items** shaped like `{ id, label, data?, children? }`:
  * `id`: must match a registered action or a built-in one
  * `label`: the text players see
  * `data`: optional parameters passed to the handler
  * `children`: optional array for submenus

<Tip>
  Start simple. Add one item, confirm it appears in the right place, then enhance the logic or add submenus.
</Tip>

### Default items: static and dynamic

* Static via config: set once, shown at the bottom of every context menu.

```lua config/contextMenus.lua theme={null}
Config.ContextMenuDefaultItems = {
  { id = 'example_goto_last_click', label = 'Go To Last Click', data = {} },
}
```

* Dynamic via API or events: add or replace at runtime from any client script.

```lua theme={null}
-- Using the registry directly (once CM is ready)
GM.ContextMenu.addDefaultItems({
  { id = 'example_stop_selected', label = 'Stop Selected', data = {} },
})

-- Or with events (does not require direct access to the registry)
TriggerEvent('gm:context_menu:add_default_items', {
  { id = 'example_goto_last_click', label = 'Go To Last Click', data = {} }
})
TriggerEvent('gm:context_menu:set_default_items', {
  { id = 'example_stop_selected', label = 'Stop Selected', data = {} }
})
```

<Warning>
  Default items must reference action IDs that are either built-in or registered by you. Avoid actions that require a specific `data.target` (for example `ped_kill`) because defaults do not automatically provide one. Prefer actions that operate on your selection or use `meta.context.ground`.
</Warning>

### Example: add quick orders to known locations

You can also mix built-in action IDs for convenience shortcuts. This example adds two global entries that use only a fixed coordinate and your current selection:

```lua config/contextMenus.lua theme={null}
Config.ContextMenuDefaultItems = {
  { id = 'goto_direct', label = 'Go to Town Square', data = { coord = vector3(-180.12, 627.84, 114.09) } },
  { id = 'attack_area', label = 'Attack in Arena', data = { coord = vector3(-279.55, 699.10, 113.50) } },
}
```

When you right-click anywhere, these entries appear. If you have peds selected, they will either walk directly to the first coordinate or engage enemies within an area around the second.

<Tip>
  Use game/admin tools to capture coordinates and paste them into `vector3(x, y, z)`.
</Tip>

### Built-in action IDs you can reuse

* Movement: `goto_direct`, `goto_path`, `goto_stand` (require `data.coord`)
* Combat: `attack_area` (requires `data.coord`)

Other IDs like `attack`, `ped_remove_weapon`, `ped_revive`, `ped_toggle_god`, `ped_toggle_freeze`, `vehicle_unmount_all`, `vehicle_destroy`, `ped_enter_vehicle`, `ped_play_anim_*`, and `ped_give_weapon_named_*` require a specific `data.target` (and sometimes more), which defaults cannot supply. Keep those for contextual menus provided by the script.

## Weapons submenu

Add or remove weapons available under "Give Weapon...". Each entry looks like:

```lua config/contextMenus.lua theme={null}
{ id = 'pistol_m1899', label = 'Pistol M1899', weapon = 'WEAPON_PISTOL_M1899' }
```

<Note>
  Use canonical RedM weapon names for the `weapon` field so the game can grant them properly.
</Note>

## Animations submenu

Control which animations appear under "Animations...". Each entry looks like:

```lua config/contextMenus.lua theme={null}
{ id = 'gentletip', label = 'Gentle Tip', dict = 'mech_loco_m@character@dutch@fancy@unarmed@idle@_variations', name = 'idle_b',
  blendInSpeed = 1.0, blendOutSpeed = -1.0, duration = 2500, flag = 31, playbackRate = 0.0 }
```

<Info>
  Flags correspond to `eScriptedAnimFlags` (for example: 1 = loop, 2 = hold last frame, 16 = upper body). Duration `-1` means use the animation's natural length.
</Info>
