> ## 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

> DD Fog of War server exports, client exports and the discovery event for treasure maps, quests and region unlocks

Everything needed to drive fog of war from another resource: reveal an area as a quest reward, check whether a player has been somewhere before offering them something, and react to first-time discoveries.

<Info>
  Every export is framework-neutral. The same call behaves identically on VORP and on RSG, because all framework access goes through the built-in bridge.
</Info>

## Conventions

Server exports are called as `exports.dd_fogofwar:Name(...)` from any server script and take the player's `source` as their first argument. Mutating exports return a boolean: `false` means the player had no resolvable character, or the region name was unknown.

Client exports are called as `exports.dd_fogofwar:Name(...)` from a client script and take no source.

## Server exports

| Export               | Signature             | Returns                                                        |
| -------------------- | --------------------- | -------------------------------------------------------------- |
| `RevealArea`         | `(src, x, y, radius)` | `boolean` - reveals and persists a circle                      |
| `RevealRegion`       | `(src, regionName)`   | `boolean` - reveals a region from `Config.Discoveries.regions` |
| `ResetPlayer`        | `(src)`               | `boolean` - wipes all stored progress for that owner           |
| `IsExplored`         | `(src, x, y)`         | `boolean` - reads the stored bitfield from the database        |
| `GetExploredPercent` | `(src)`               | `number` - 0 to 100, returns `100.0` on a full reveal          |

### RevealArea

Reveals a circular area and writes it to the database, so it survives relogs and restarts. This is the export to use for treasure maps, cartography rewards and story unlocks.

```lua theme={null}
-- A treasure map hands the player the region around Bacchus Station
exports.dd_fogofwar:RevealArea(source, -1300.0, 640.0, 500.0)
```

`radius` is in world units. The circle is decomposed into explored cells at `Config.CellSize` resolution, so very small radii snap to at least one cell.

### RevealRegion

The same thing by name, using a region already defined in `Config.Discoveries.regions`. Keeps the coordinates in the config instead of spread across your scripts.

```lua theme={null}
exports.dd_fogofwar:RevealRegion(source, 'valentine')
```

Returns `false` and logs a debug line if no region with that name exists.

### ResetPlayer

Wipes every stored chunk, the full-reveal marker and all discovery records for that owner, then resets the client's fog immediately.

```lua theme={null}
-- New character, blank map
exports.dd_fogofwar:ResetPlayer(source)
```

<Warning>
  This is destructive and takes effect at once. Under `PersistenceMode = 'account'` it wipes the progress of every character on that account, not just the active one.
</Warning>

### IsExplored

Checks a world position against the player's stored exploration. Useful for gating: only offer a fast travel destination, a delivery job or a map marker for places the player has actually been.

```lua theme={null}
if exports.dd_fogofwar:IsExplored(source, coords.x, coords.y) then
    -- offer the destination
end
```

<Info>
  This reads from the database on every call, so it is not something to run in a loop. Check once when a menu opens or a job is offered, not per frame.
</Info>

### GetExploredPercent

The share of the playable map the player has uncovered, as a number between 0 and 100. Returns `100.0` for a fully revealed map without counting cells.

```lua theme={null}
local percent = exports.dd_fogofwar:GetExploredPercent(source)
print(('%.1f%% of the map explored'):format(percent))
```

The playable area is derived from `Config.MapBounds`, so a custom map needs those bounds adjusted for the number to mean anything.

## Client exports

| Export       | Signature | Returns                                                       |
| ------------ | --------- | ------------------------------------------------------------- |
| `IsExplored` | `(x, y)`  | `boolean` - checks the in-memory grid, no database round trip |
| `IsActive`   | `()`      | `boolean` - whether fog of war is running for this player     |

`IsExplored` on the client answers from the cached grid, counts `Config.PreRevealedZones` as explored, and returns `true` for everything while the map is fully revealed or while the resource is inactive. It is cheap enough to call per blip or per marker, which is exactly what the blip manager integration does.

```lua theme={null}
local coords = GetEntityCoords(PlayerPedId())
if exports.dd_fogofwar:IsExplored(coords.x, coords.y) then
    -- draw the marker
end
```

## Events

### dd\_fogofwar:discovered

A server event, fired once per character the first time a discovery happens. Both zone discoveries and custom regions use it.

```lua theme={null}
AddEventHandler('dd_fogofwar:discovered', function(src, ownerId, discoveryKey)
    -- your code
end)
```

| Argument       | Type     | Meaning                                                                                   |
| -------------- | -------- | ----------------------------------------------------------------------------------------- |
| `src`          | `number` | The player's server id                                                                    |
| `ownerId`      | `string` | The persistence owner: character id, or account id under `PersistenceMode = 'account'`    |
| `discoveryKey` | `string` | `district:<key>` or `town:<key>` for game zones, the configured `name` for custom regions |

Zone keys are defined in `shared/zones.lua`. Custom region keys are whatever you set as `name` in `Config.Discoveries.regions`.

<Warning>
  Zone keys come straight from the game and their casing is not consistent: `town:valentine` and `town:Rhodes` and `town:StDenis` all coexist. Copy the exact key out of `shared/zones.lua` instead of guessing it from the label.
</Warning>

```lua theme={null}
-- Announce the first arrival in Saint Denis
AddEventHandler('dd_fogofwar:discovered', function(src, ownerId, key)
    if key == 'town:StDenis' then
        TriggerClientEvent('chat:addMessage', -1, {
            args = { 'Frontier', ('%s has reached Saint Denis'):format(GetPlayerName(src)) },
        })
    end
end)
```

<Info>
  The event fires after the discovery has been recorded, so it will not fire again for that character on a relog. Rewards configured in `Config.Discoveries` are paid by the resource itself; use this event for anything beyond money and items.
</Info>

## Blip integration

`Config.HideBlipsInFog` wires fog of war into the free DD Blip Manager companion resource. On character load, fog of war registers a rule with the blip manager that hides any blip sitting on an unexplored cell, and refreshes it whenever the fog state changes.

If you build your own visibility logic on top, the blip manager exposes `SetRuleEnabled`, `RegisterRule` and `Refresh` for exactly that. Fog of war owns the rule named `fow`; register your own under a different name rather than overriding it.
