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

# Setup

> Install and configure DD Fog of War - persistence, cell size, discoveries, rewards, blip hiding and admin commands

## Installation

<Steps>
  <Step title="Download">
    Get the latest release from our [Tebex store](https://tebex.dietrich-development.com) and download it from your [Keymaster](https://portal.cfx.re/assets/granted-assets)
  </Step>

  <Step title="Extract">
    Extract the `dd_fogofwar` folder to your server's `resources` directory
  </Step>

  <Step title="Ensure">
    Add `ensure dd_fogofwar` to your `server.cfg`, after oxmysql and your framework core
  </Step>

  <Step title="Grant the admin permission">
    Add `add_ace group.admin dd_fogofwar.admin allow` to your `server.cfg`
  </Step>

  <Step title="Configure">
    Adjust `config/config.lua` to your liking. The database tables are created automatically on first start.
  </Step>
</Steps>

<Info>
  The only hard dependency is `oxmysql`. The framework bridge detects VORP or RSG on its own, so no framework-specific setup is needed.
</Info>

## Configuration

Everything lives in `config/config.lua`.

### Core options

```lua theme={null}
-- Master switch. When false the resource does nothing (map keeps default behavior).
Config.Enabled = true

-- Print debug output (client and server).
Config.Debug = false

-- 'character': every character has its own exploration progress.
-- 'account': all characters of a player share one exploration progress.
Config.PersistenceMode = 'character'
```

### Resolution and reveal

`CellSize` is the world size of one exploration cell. Smaller cells give a finer map but store more data. `RevealScale` is the size of the engine's own live reveal around the moving player.

```lua theme={null}
-- World-unit size of one exploration cell in meters. The in-game reveal radius per
-- cell is controlled by RevealScale; 100.0 with scale 1.0 gives gapless coverage.
Config.CellSize = 100.0

-- Scale of the engine's live reveal around the moving player, passed to
-- SetMinimapFowOverrideRevealScale. NEVER set this to 0.0: the engine FOW
-- bugs out and stops revealing.
Config.RevealScale = 1.0

-- How long restored reveal volumes stay alive (ms). FOW opacity accumulates
-- while a reveal writer is active; too short leaves a washed-out veil over
-- restored areas. Only relevant during login replay / admin reveals.
Config.RevealHoldMs = 8000

-- Maximum reveal volumes used to restore stored exploration. If the exact
-- rectangle decomposition needs more, cells are coarsened (2x, 4x, ...) until
-- the count fits; edges then snap to the coarser grid.
Config.MaxRevealVolumes = 768
```

<Warning>
  Never set `RevealScale` to `0.0`. The engine's fog of war stops revealing entirely and the map freezes in whatever state it was in.
</Warning>

<Warning>
  `RevealHoldMs` is not a cosmetic delay. Fog opacity accumulates for as long as a reveal volume is alive, so a short hold leaves restored areas under a permanent half-transparent veil instead of fully uncovered. Lower it only if you know what a shorter hold looks like on your map.
</Warning>

### Sampling and flushing

```lua theme={null}
-- Milliseconds between player position samples for exploration tracking.
Config.SampleInterval = 750

-- Cell radius recorded as explored around the player per sample. Should
-- roughly match the engine's own live reveal radius so the restored map
-- equals what the player actually saw.
Config.SampleRingRadius = 2

-- Milliseconds between automatic delta flushes to the server.
Config.FlushInterval = 20000

-- Server-side validation: maximum chunks accepted per flush payload.
Config.MaxChunksPerFlush = 32

-- Server-side validation: minimum milliseconds between flushes per player.
Config.MinFlushGap = 5000
```

`MaxChunksPerFlush` and `MinFlushGap` are the server's rate limit against forged payloads. Raise them only if you also raised `SampleRingRadius` or lowered `FlushInterval` far enough that legitimate flushes start getting rejected.

### Guarma and blips

```lua theme={null}
-- Hide the fog overlay while the player is in Guarma (broken visuals otherwise).
Config.HandleGuarma = true

-- Hide map blips that sit in undiscovered areas, like singleplayer POIs.
-- Requires the free dd_blipmanager resource; ignored when it is not running.
-- This switch is authoritative: it overrides dd_blipmanager's own Fow.enabled.
Config.HideBlipsInFog = true
```

`HideBlipsInFog` needs the free companion resource `dd_blipmanager` to be running. Without it the switch is simply ignored, no error. When both are running, this switch wins over the blip manager's own setting, so fog of war stays the single place you configure it.

### Pre-revealed zones

Areas that are always visible and never written to the database. Useful for the spawn town or a starting region.

```lua theme={null}
-- Zones revealed on every load without being persisted (towns, spawn points...).
-- Circle zones: name, coords, radius (meters).
Config.PreRevealedZones = {
    -- { name = 'valentine', coords = vector3(-275.0, 802.0, 119.0), radius = 400.0 },
}
```

### Map bounds

```lua theme={null}
-- World bounds of the playable map, used for zone scans and the explored-percent
-- calculation. Only change these when using a custom map.
Config.MapBounds = { minX = -8000.0, maxX = 4500.0, minY = -4500.0, maxY = 7000.0 }
```

### Discoveries

A discovery fires once per character on first visit. It shows a notification, optionally pays a reward, and fires the server event other resources can listen to.

<Accordion title="Discovery modes">
  * `zones`: fully dynamic, driven by the game's own districts and towns, the same zones the game shows when you cross a region border. No coordinates needed.
  * `custom`: only the circle regions you configure yourself.
  * `both`: zones and custom regions together.
</Accordion>

```lua theme={null}
Config.Discoveries = {
    enabled = true,
    notify = true,
    mode = 'zones',

    zones = {
        district = true,          -- discover districts (Heartlands, Big Valley, ...)
        town = true,              -- discover towns (Valentine, Rhodes, ...)
        -- Reveal the whole zone area on the map on first entry, per zone kind.
        -- Districts are large; by default only towns reveal their full shape
        -- and district discovery just notifies and rewards.
        revealZone = { district = false, town = true },
        persistReveal = true,     -- store the revealed zone as explored
        scanPointsPerFrame = 400, -- zone shape scan workload per frame
        -- Reward for every zone discovery; per-zone overrides win.
        -- Keys: 'district:<key>' / 'town:<key>' as defined in shared/zones.lua.
        defaultReward = nil,      -- e.g. { money = 0.25, item = nil, amount = 1 }
        rewards = {
            -- ['town:valentine'] = { money = 0.50 },
            -- ['district:Heartlands'] = { money = 1.00 },
        },
    },

    regions = {
        -- {
        --     name = 'valentine',
        --     label = 'Valentine',
        --     coords = vector3(-275.0, 802.0, 119.0),
        --     radius = 400.0,
        --     reward = { money = 0.50, item = nil, amount = 1 },
        -- },
    },
}
```

Set `notify = false` to keep the discoveries and rewards but drop the on-screen notification.

### Permission and command

```lua theme={null}
-- Ace permission required for the admin command, e.g.
-- add_ace group.admin dd_fogofwar.admin allow
Config.Permissions = {
    adminCommand = 'dd_fogofwar.admin',
}

-- Admin command name: /fow reveal|reset|stats [serverId]
Config.Command = 'fow'
```

## Admin commands

```
/fow reveal [serverId]   Reveal the whole map for a player (persisted)
/fow peek   [serverId]   Session-only toggle: show the whole map, call again to restore
/fow reset  [serverId]   Wipe a player's exploration progress
/fow stats  [serverId]   Show stored chunks and explored percentage
```

Without a server id the command applies to the caller. All four also work from the server console, where the server id is required.

<Info>
  `peek` is the one to reach for while building or testing. It reveals everything for the current session only and changes nothing in the database, so calling it a second time puts the player's real progress back.
</Info>

## Localization

All player-facing strings live in `config/language.lua`:

```lua theme={null}
Lang = {
    discovered_title = 'Region discovered',
    discovered_desc = 'You have discovered %s',
    admin_revealed = 'Map fully revealed for player %s',
    admin_reset = 'Fog of war reset for player %s',
    admin_stats = 'Player %s: %d chunks stored, %.1f%% explored',
    no_permission = 'You do not have permission to use this command',
    usage = 'Usage: /%s reveal|reset|stats [serverId]',
}
```

## Database

Three tables are created automatically on first start:

| Table                     | Contents                                                        |
| ------------------------- | --------------------------------------------------------------- |
| `dd_fogofwar_chunks`      | Exploration bitfields, one row per 6.4 x 6.4 km chunk per owner |
| `dd_fogofwar_full_reveal` | Markers for fully revealed maps                                 |
| `dd_fogofwar_discoveries` | First-visit records for discovery regions                       |

Wiping a player is `/fow reset`; wiping everyone is a `TRUNCATE` on all three tables while the resource is stopped.

## Troubleshooting

<Accordion title="The whole map is revealed on login">
  Some frameworks reveal the map by default. The resource reverts this on character load, so this normally resolves itself. If it persists, check whether another resource calls a full map reveal after character selection.
</Accordion>

<Accordion title="Explored areas look washed out instead of fully uncovered">
  `RevealHoldMs` is too low. Fog opacity builds up only while a reveal volume is alive, so a short hold leaves a veil behind. Put it back to `8000`.
</Accordion>

<Accordion title="The pause map does not update">
  The pause menu map texture refreshes lazily. Close the map and open it again before judging the fog state.
</Accordion>

<Accordion title="Blips are still visible in undiscovered areas">
  Check that `dd_blipmanager` is running (`ensure dd_blipmanager` in `server.cfg`) and that `Config.HideBlipsInFog` is `true`. Blips attached to an entity are exempt by design, because parking them would fight the attachment.
</Accordion>

<Accordion title="Flushes are being rejected">
  Enable `Config.Debug` and watch the server output. If you lowered `FlushInterval` or raised `SampleRingRadius`, raise `MaxChunksPerFlush` and lower `MinFlushGap` to match.
</Accordion>
