Skip to main content

Overview

DD Gamemaster is your control room for live events and storytelling. Open the UI, pick from hundreds of NPCs and animals, and then right‑click the world to give clear, game‑native orders: move here, stand there, attack that, mount this horse, play an animation, and more. You set everything up using only the config/ folder and the frameworkBridge. No code changes are required. Within minutes, you can tailor the tool to your server style and empower staff to stage scenes smoothly.
What you’ll do most of the time: choose who to spawn, select them, right‑click somewhere, and pick an action. The UI translates your choice into in‑game orders for the selected entities.

How it works at a glance

  • Selection: Click or drag to select one or more peds or vehicles.
  • Context menu: Right‑click ground, a ped, or a vehicle to see relevant actions.
  • Orders: Actions like go to, attack, dismount, give weapon, play animation. The script handles pathing, hostility, safety checks, and timing.
  • Your configuration: Control the catalog, languages, permissions, and menu content entirely from config/.

Quickstart

1

Grant permission to use Gamemaster

Add an ACE permission to your server config so your admins can use the tool.
server.cfg
add_ace group.admin dd_gamemaster.admin allow
add_principal identifier.steam:110000112345678 group.admin
Restart the resource and verify that an allowed user can toggle the tool.
2

Set the command, language, and debug mode

Open config/config.lua and adjust basic options:
config/config.lua
Config.ToggleCommand = 'gm'       -- Type /gm in chat or run gm in console
Config.Language = 'en'            -- 'en' or 'de' (see config/language.lua)
Config.Debug = false              -- Set true to see development diagnostics
Check every config file carefully and set them up to your likings

Tutorial pages

Control the built‑in onboarding/tutorial carousel via config/tutorial.lua.
config/tutorial.lua
Config.Tutorial = {
  pages = {
    {
      id = 'welcome',
      title = 'Welcome to Gamemaster',
      text = 'Lets take our first steps... ',
      media = 'images/animations/tutorial_opener_short.webp',
      mediaAlt = 'Welcome'
    },
    -- add, remove, or reorder pages freely
  }
}
  • id: stable identifier used internally.
  • title/text: content shown in the UI.
  • media: optional relative path under ui/dist/ (WebP, GIF, PNG).
  • mediaAlt: optional accessible description.
3

Reload and test

Reload the resource and toggle the UI to confirm your configuration.
Console
restart dd_gamemaster
Use default /gm or your custom command in-game to open/close the UI.

Using the UI

Spawning items

  • Select and spawn: Left-click an item in the grid to select it, then click in the world to spawn it.
  • Item options and variants: Right-click an item to see options or choose among variants (when available).
  • Find items fast: Use the search bar and filters to narrow results.

Favorites

  • Assign by drag: Drag items from the grid onto the numbered 1–9 slots.
  • Select favorite: Press a digit key 1–9 to select a favorite.
  • Quick-assign: Press 1–9 while hovering an item to assign it to that slot.

Categories & filters

  • Switch categories to browse different item types.
  • Use filters to refine results by tags and properties.
  • Reset clears all filters and the current search query.

Keyboard shortcuts

Camera controls

  • Move: W A S D
  • Up / Down: Space / C
  • Sprint: Shift
  • Zoom: Mouse Wheel
  • Rotate camera: Middle Mouse Button + Move
  • Yaw: Q E or
  • Pitch: R F or

Selection and actions

  • Select entity under cursor: Left Mouse Button
  • Box-select (drag): Left Mouse Button + Drag
  • Open context menu: Right Mouse Button
  • Move order (with selection): Right Mouse Button + Drag
  • Return to Select mode: Esc
  • Cancel spawn mode: Right Mouse Button
  • Highlight all peds: Tab
  • Copy selection: Ctrl + C
  • Paste at cursor: Ctrl + V
  • Cut selection: Ctrl + X
  • Delete selection: Delete / Backspace

Favorites

  • Select favorite: 1–9
  • Assign favorite (while hovering an item): 1–9

Advanced features

Search is debounced and covers item names and tags. Examples:
  • "sheriff" — finds Sheriff NPCs
  • "lawman" — finds law enforcement NPCs
  • "combat" — finds combat-related presets

Activity log

The log drawer records your actions, supports filtering, and can be exported. Useful for debugging or reviewing a session.

Marquee selection

Drag the left mouse in empty world space to box-select multiple entities quickly.

Ped info panel

When exactly one ped is selected, a compact panel shows model, HP, weapon, relationship, and ownership.

Core settings

All core settings live in config/config.lua.

General

  • Config.Debug: Enables verbose logging via Bridge.Debug(...).
  • Config.Language: Sets UI language. Supported keys match Language.* tables in config/language.lua (default: en, also de).
  • Config.ToggleCommand: Chat/console command to toggle Gamemaster UI (default: gm).
  • Config.stayInvisibleAfterLeavingGm: If true, you remain invisible after leaving GM mode.

Camera and movement

  • Config.InitialAltitude: Starting camera height above ground.
  • Config.MinAltitude / Config.MaxAltitude: Altitude limits.
  • Config.MoveSpeed: Base lateral movement speed; combine with sprint multiplier.
  • Config.MoveSpeedSprintMultiplier: Hold Shift to move faster by this factor.
  • Config.ZoomSpeed: Mouse wheel zoom speed (height delta).
  • Config.RotateSpeed: Rotation speed when using arrow keys.
  • Config.MouseRotateSensitivity: MMB rotation sensitivity.
  • Config.SelectionMaxDistance: Maximum distance for selectable peds from the camera.
config/config.lua
Config.InitialAltitude = 25.0
Config.MinAltitude = 2.0
Config.MaxAltitude = 150.0
Config.MoveSpeed = 12.0
Config.MoveSpeedSprintMultiplier = 4.0
Config.ZoomSpeed = 6.0
Config.RotateSpeed = 120.0
Config.MouseRotateSensitivity = 180.0
Config.SelectionMaxDistance = 350.0

Network indicator

Configure the on-screen indicator that shows networked entity usage.
config/config.lua
Config.NetworkIndicator = {
  enabled = true,
  maxCapacity = 110,
  Notify = {
    enabled = false, -- enable pop-up warning via your bridge
  },
  thresholds = {
    yellow = 76,
    orange = 91,
    red = 101,
  },
  minVisible = 1,
}
Above ~90 entities you may see performance issues. The hard limit is around 110 on RedM.

Notifications

  • Enable Config.NetworkIndicator.Notify.enabled = true to show a warning when the networked ped count nears or exceeds capacity. This uses Bridge.notify(...) and localized strings NotifyHighNetworkPoolTitle and NotifyHighNetworkPoolText from config/language.lua.

Markers and overlays

Configure selection/destination marker colors, move order indicator style, and optional infrared vision overlay.
config/config.lua
Config.DrawMarkers = {
  -- Disable all drawing for clean screenshots
  screenShotMode = false,
  selection = {
    ped = { r = 0, g = 128, b = 255 },
    vehicle = { r = 255, g = 165, b = 0 },
  },
  destination = {
    line = { r = 0, g = 200, b = 0 },
    marker = { r = 0, g = 200, b = 0 },
  },
  moveOrder = {
    -- 'rotate' shows a rotating circle, 'arrow' shows a directional arrow
    type = 'rotate',
  },
  -- Toggle an infrared-style highlight overlay while in GM mode
  InfraredVision = true,
}
All colors are RGB integers 0–255. Switch moveOrder.type between rotate and arrow based on preference. Turn on screenShotMode to hide markers while capturing footage.

Health bar colors

Tune the gradient and alpha used by the on-entity health bars.
config/config.lua
Config.HealthBar = {
  -- Gradient colors
  colorLow = { r = 255, g = 60, b = 60 },
  colorMid = { r = 255, g = 165, b = 0 }, -- optional midpoint; remove to blend low→high
  colorHigh = { r = 51, g = 189, b = 51 },

  -- Background rectangle RGBA
  background = { r = 20, g = 20, b = 20, a = 180 },

  -- Foreground (fill) opacity 0–255
  foregroundAlpha = 230,
}
Lower foregroundAlpha for subtler bars; raise background.a if the bar is hard to see against bright scenes.

Permissions and access control

Control who can toggle Gamemaster with a single function.
config/config.lua
Config.Permissions = {
  useGameMaster = function(src)
    return IsPlayerAceAllowed(src, "dd_gamemaster.admin")
  end,
}
You can combine checks (ACE + job + groups) in the same function when needed.

Context menu customization

Use config/contextMenus.lua to configure weapons, animations, and now 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

config/contextMenus.lua
-- 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.
config/contextMenus.lua
-- 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)
If you want your Hello World to always be visible, add it as a default item instead:
config/contextMenus.lua
Config.ContextMenuDefaultItems = {
  { id = 'example_hello_world', label = 'Hello World', data = { message = 'Always visible' } },
}

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
Start simple. Add one item, confirm it appears in the right place, then enhance the logic or add submenus.

Default items: static and dynamic

  • Static via config: set once, shown at the bottom of every context menu.
config/contextMenus.lua
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.
-- 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 = {} }
})
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.

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:
config/contextMenus.lua
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.
Use game/admin tools to capture coordinates and paste them into vector3(x, y, z).

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:
config/contextMenus.lua
{ id = 'pistol_m1899', label = 'Pistol M1899', weapon = 'WEAPON_PISTOL_M1899' }
Use canonical RedM weapon names for the weapon field so the game can grant them properly.

Animations submenu

Control which animations appear under “Animations…”. Each entry looks like:
config/contextMenus.lua
{ 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 }
Flags correspond to eScriptedAnimFlags (for example: 1 = loop, 2 = hold last frame, 16 = upper body). Duration -1 means use the animation’s natural length.

Data, categories, and items

Customize what appears in the grid UI using config/data.lua.

Categories

Define your high-level categories (order and icon are supported):
config/data.lua
Data.categories = {
  { id = 'npcs', label = T('NPCs', 'NPCs'), order = 1, icon = '👥' },
  { id = 'animals', label = T('Animals', 'Animals'), order = 2, icon = '🐾' },
}

Custom items

Add curated NPCs or animals you want to highlight. You only need id, name, type, and model. Optional fields include image, tags, condition, and variants (for grouped horses).
config/data.lua
Data.items = {
  -- NPC example
  { id = 'sheriff_johnson', name = 'Sheriff Johnson', type = 'npc', model = 'CS_LawCarl',
    image = 'images/items/sheriff.webp', tags = { 'lawman', 'authority' }, condition = 'isAdmin' },

  -- Animal example
  { id = 'outlaw_wolf', name = 'Wolf', type = 'animal', model = 'A_C_Wolf',
    tags = { 'animal', 'dangerous' }, condition = 'anyone' },
}
label = T('SomeKey', 'Fallback') uses the active language from config/language.lua with a safe fallback.

Conditions

Gating logic lives in Data.conditions. Reference by string from an item’s condition field.
config/data.lua
Data.conditions = {
  anyone = function()
    return true
  end,
  isAdmin = function()
    local player = Bridge.getPlayerData(source)
    return player.job == 'admin'
  end,
}
Define as many as you need and reuse them across items.

Default favorites

Seed the 1–9 favorites bar for first‑time users with Data.defaultFavorites. Values are item ids or nil.
config/data.lua
Data.defaultFavorites = {
  'sheriff_johnson', -- 1
  nil,               -- 2
  'outlaw_wolf',     -- 3
  nil, nil, nil, nil, nil, nil
}
If server‑side favorites are present, they override these defaults after character selection.

Horse mount models

The list Data.horseMountModels powers the “Spawn on Horse” option with valid horse models. You can add or remove entries safely.
config/data.lua
Data.horseMountModels = {
  'A_C_Horse_Arabian_Black',
  'A_C_Horse_Turkoman_Gold',
}

Generated items

config/data_items_generated.lua contains a large, generated list of NPCs and animals. The UI automatically merges it with your Data.items while avoiding duplicates and grouping horse variants by breed.
Avoid manual edits to config/data_items_generated.lua as it is intended to be machine-generated and may be replaced by updates.

Item images and file paths

Items display an image in the grid. You can either point to a custom image on disk or rely on the script’s default naming rules.

Where images live

Images are served from the resource UI:
ui/dist/images/items/
Place WebP images in that folder. The fxmanifest.lua already exposes this path to the game UI.

How the path is chosen

  • If you set image on an item, that path is used as‑is.
  • If you do not set image, the script builds a filename from the item id or model:
    • For custom items in config/data.lua: images/items/<id>.webp
    • For generated items in config/data_items_generated.lua: images/items/<sanitized_model>.webp
Sanitized model means lowercase, spaces to _, and only letters, numbers, and _. For example A_C_Horse_Turkoman_Gold becomes a_c_horse_turkoman_gold.webp.

Adding custom images

1

Pick a filename that matches the item

For a custom item with id = 'sheriff_johnson', create ui/dist/images/items/sheriff_johnson.webp.
2

Override the image path if needed

You can point to a different file by setting image on the item.
config/data.lua
{ id = 'sheriff_johnson', name = 'Sheriff Johnson', type = 'npc', model = 'CS_LawCarl',
  image = 'images/items/special_sheriff.webp', tags = { 'lawman' }, condition = 'anyone' }
3

Provide images for generated models you care about

For generated items, drop files named after the sanitized model:
ui/dist/images/items/a_c_wolf.webp
ui/dist/images/items/a_c_bear_black.webp
ui/dist/images/items/cs_lawcarl.webp
You don’t need to cover every model. The UI can still show items without custom images.
Use WebP format to keep file sizes small and loading fast. Recommended resolution is around 256–512 px on the short edge.

Language and localization

Localize all UI strings in config/language.lua. Two languages ship by default: English (Language.en) and German (Language.de).
  • Change active language by setting Config.Language = 'en' or Config.Language = 'de' in config/config.lua.
  • Edit text by changing values inside the language tables. Keep keys stable across languages.
config/language.lua
Language.en["SearchItemsPlaceholder"] = "Search items... (Ctrl+F)"
Language.de["SearchItemsPlaceholder"] = "Elemente suchen... (Strg+F)"
Respect placeholders like {name}, {slot}, {count} when translating. They are replaced at runtime.

Testing and troubleshooting

  • Toggle command not working: Confirm your permission function returns true for your account. In ACE mode, verify your identifiers and group mapping.
  • UI shows no items: Ensure config/data_items_generated.lua is loaded in fxmanifest.lua (it is by default) and that Data.items merges correctly. Use Config.Debug = true and Bridge.Debug(...) to inspect.
  • Network indicator missing: Check Config.NetworkIndicator.enabled = true and your entity counts exceed minVisible.
  • Animations not playing: Verify the dict and name pair exists in RedM; test with a simpler known animation first.
When everything is configured, /gm should open the UI, items should load, and context menu actions should work according to your permissions.

Reference snippets

Minimal working configuration

config/config.lua
Config.Debug = false
Config.Language = 'en'
Config.ToggleCommand = 'gm'

Config.NetworkIndicator = {
  enabled = true,
  maxCapacity = 110,
  thresholds = { yellow = 76, orange = 91, red = 101 },
  minVisible = 1,
}

Config.Permissions = {
  useGameMaster = function(src)
    return IsPlayerAceAllowed(src, 'dd_gamemaster.admin')
  end,
}

Example custom items with a guard

config/data.lua
Data.conditions.isGM = function()
  return Bridge.hasGroup and Bridge.hasGroup(source, 'gamemaster')
end

Data.items = {
  { id = 'gm_only_deer', name = 'Deer', type = 'animal', model = 'A_C_Deer_01', condition = 'isGM' },
}
If your bridge exposes different helpers, adapt the examples accordingly (e.g., Bridge.getGroups, Bridge.getJob, Bridge.getPlayerData).
I