# Game cursor, order markers and rings (ui.cursor) ## What it is for `ui.cursor` is for mouse-driven games (MOBA, RTS, action RPG, top-down). It replaces the system pointer with a game cursor, leaves a marker on the ground where the player gives an order (arrows closing on the spot for a move, red for an attack) and, when asked, draws coloured rings on the ground under characters (the hero, a downed ally). The kit decides nothing about the order itself: the kit that turns a click into an order emits `pointer.command`, and `ui.cursor` answers. It draws nothing on its own; the display module of the kit draws the markers and the rings, and the page draws the cursor from the variables. For the other screens of the interface, see the [interface guide](guide:ui-screens). ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "ui.cursor" } gripforge_gamekit_configure { project_id: "gkp_…", id: "ui.cursor", config: { "cursor": "crosshair", "marker": "ring", "markerSeconds": 0.8 } } ``` It requires `game.engine` only. The cursor turns to its `attack` mode over an enemy when `combat.damage` is installed. ## First example A click-to-move kit emits the order; `ui.cursor` turns it into a marker event, and the display module draws it: ```json { "topic": "pointer.command", "payload": { "point": [2, 0, 3], "kind": "move" } } ``` becomes `fx.ground_marker { position: [2, 0, 3], color: "#3ee06a", seconds: 0.55, size: 1.8, style: "arrows" }`. For `kind: "attack"` the colour is `attackColor` and the size is 85 % of `markerSize`. The marker closes on the spot, then fades; a new marker at the same spot replaces it, and the oldest goes when there are too many. ## Settings and defaults | Setting | Type | Default | Meaning | |---|---|---|---| | `cursor` | string | `gauntlet` | `gauntlet`, `arrow`, `crosshair` or `system` (the browser pointer). | | `cursorColor` | string | `#d8dde6` | Cursor body colour. | | `cursorSize` | integer | `32` | Cursor size in pixels (16 to 64). | | `marker` | string | `arrows` | Ground marker of a click: `arrows`, `ring` or `none`. | | `moveColor` | string | `#3ee06a` | Marker colour of a move order. | | `attackColor` | string | `#ff4d4d` | Marker and cursor colour of an attack order. | | `markerSeconds` | number | `0.55` | How long the marker stays (0.15 to 3). | | `markerSize` | number | `1.8` | Marker radius in metres (0.3 to 6). | | `rings` | list | `[]` | Ring rules, up to 16 (see below). Empty: no ring. | Colours are `#rrggbb`; anything else falls back to the default. ### Rings Each entity takes the first rule of `rings` that matches it. A rule has: | Field | Default | Meaning | |---|---|---| | `tag` | (required) | The tag an entity carries to get this ring (`player`, `enemy`, `downed`, `ally`...). | | `who` | `any` | `any`, `local` (only the character the camera follows) or `others` (every one but it). | | `unless` | `[]` | No ring for an entity that also carries one of these tags (up to 8). | | `color` | `#2eb8d4` | Ring colour. | | `radius` | `0.6` | Radius to the middle of the band, metres (0.1 to 5). | | `width` | `0.04` | Thickness of the band, metres (0.005 to 1). | | `opacity` | `1` | 0 to 1. | | `pulse` | `0` | Pulses per second (0 to 10); 0: steady. | | `lift` | `0.03` | Height above the feet, metres (0 to 1). | | `lit` | `true` | Lit by the scene like the ground, or drawn flat (false: readable in the dark). | ```json { "rings": [ { "tag": "downed", "who": "others", "color": "#ac302b", "pulse": 1.2, "lit": false }, { "tag": "player", "who": "local", "color": "#2eb8d4" } ] } ``` ## Service, variables, events Service `ui.cursor`: - `mark(position, kind?)`: leave a ground marker at `[x, y, z]`; `kind` is `"attack"` or anything else for a move. - `setMode(mode)`: force the cursor mode (`default`, `attack`, `ally`, `blocked`). An empty value gives control back to the automatic mode. Variables the page and the engines read: `ui.cursor.style`, `ui.cursor.mode`, `ui.cursor.color`, `ui.cursor.attack_color`, `ui.cursor.size` and `ui.cursor.rings` (the rules, cleaned). Events: the kit listens to `pointer.command { point, kind, target? }` and emits `fx.ground_marker { position, color, seconds, size, style }`. A `point` that is not three finite numbers, and the style `none`, produce no marker. ## Hooks and modding No hook: every setting is a look, and all of them are moddable. A mod can restyle the cursor and the marker or add ring rules. The asset `cursor_image` (a small square image, hotspot at the top-left tip) replaces the drawn cursor. ## Engines The marker events and the variables are the same everywhere; the web page draws the cursor, and the web and Bevy renderers draw the markers and the rings. ## When it does not do what you expect - No marker after a click: `marker` is `none`, or the kit that handles clicks does not emit `pointer.command` with a `point` of three numbers. - The cursor never turns to `attack`: it needs `combat.damage`, a player with a team in `combat.health`, and `aim.point` (or `aim.target`) published by an aiming kit; the test runs every six ticks. - A forced mode stays: call `setMode("")`. - No ring: `rings` is empty, no rule's `tag` matches, or an `unless` tag is present. ## Limits It does not handle the click, pathfinding or the order itself, and it draws nothing in the scene by itself. ## Versions Kit version 1.2.0 (rings under characters); the cursor, the markers and the modes came with 1.0.0.