# Automatic Doors

A UE4SS Lua mod for RuneScape: Dragonwilds that:
- automatically **opens** a door when a player gets within a configurable
  radius of it, and
- automatically **closes** a door a configurable number of seconds after
  no player remains within that radius.

## Why this version looks the way it does

This went through three designs:

1. **Polling everything every 2 seconds.** Confirmed correct by live
   testing, but caused noticeable game lag.
2. **Event-driven, hooking the game's native "show/hide interaction
   prompt" events.** This would have been the cheapest possible approach
   (zero recurring scans, reacts only at the exact moment a player enters/
   exits range) - but live testing with unconditional diagnostic logging
   showed these specific hooks never fire during real gameplay. Whatever
   actually drives the interaction prompt doesn't go through them, so this
   approach was dropped rather than guessing at further hook candidates.
3. **This version: polling again, but the expensive part is decoupled
   from the frequent part.** The actual cost driver in version 1 was
   `FindAllOf()`, which scans the entire live UObject array - and it was
   being called every 2 seconds. Now that full-world scan only happens on
   a slow timer (`RescanIntervalMs`, default 30s) that rebuilds a small
   cached list of known doors and players. A fast timer (`CheckIntervalMs`,
   default 1.5s) only does cheap distance/state math against that already-
   resolved cached list - no world scan in the hot path at all.

## Requirements

- UE4SS installed for RuneScape: Dragonwilds (the "UE4SS for RSDragonwilds"
  mod on Nexus Mods is the standard way to get this).

## Install

1. Copy this entire `Automatic Doors` folder into your UE4SS `Mods` folder:
   ```
   ...\RSDragonwilds\RSDragonwilds\Binaries\Win64\ue4ss\Mods\Automatic Doors\
   ```
   so that you end up with:
   ```
   Mods\Automatic Doors\enabled.txt
   Mods\Automatic Doors\scripts\main.lua
   Mods\Automatic Doors\scripts\config.txt
   ```
2. The included `enabled.txt` is enough to activate it - you don't need to
   edit `mods.txt`.
3. Launch the game. Check `UE4SS.log` (same `ue4ss` folder) for a line like:
   ```
   [Lua] [Automatic Doors] Initialized (cached polling). AutoOpen=on (radius=250 units). Doors auto-close 30s after everyone leaves range. Check every 1500ms, rescan every 30000ms.
   ```
   followed shortly by:
   ```
   [Lua] [Automatic Doors] Rescanned world: 34 known door(s), 1 player(s) cached.
   ```

## Configuring

Edit `Mods\Automatic Doors\scripts\config.txt`:

```
CloseAfterSeconds=30
AutoOpenEnabled=1
AutoOpenRadiusUnits=250
CheckIntervalMs=1500
RescanIntervalMs=30000
```

- `CloseAfterSeconds` - how long with no player in range before a door
  auto-closes.
- `AutoOpenEnabled` - `1` to auto-open doors on approach, `0` to disable
  (the mod will then only ever close doors).
- `AutoOpenRadiusUnits` - how close a player must be to a closed door
  before it opens (1 unit = 1 cm).
- `CheckIntervalMs` - how often the cheap cached-list check runs. Safe to
  lower if you want snappier response - this pass doesn't scan the world.
- `RescanIntervalMs` - how often the expensive world-scan refresh runs.
  This is the one that matters for performance - don't set this too low.
  The trade-off: doors built, or players joining/leaving, won't be picked
  up by this mod until the next rescan.

If you build a new door and want it picked up immediately rather than
waiting for the next scheduled rescan, press **Ctrl+F4** to force one.

After editing config.txt, either restart the game, or use UE4SS's GUI
console (Console tab -> "Restart All Mods"), or enable Hot Reload in
`UE4SS-settings.ini` and press the configured hot-reload key (Ctrl+R by
default).

## Manual test key-binds

- **Ctrl+F2** - immediately closes every currently-open known door.
- **Ctrl+F3** - immediately opens every currently-closed known door.
- **Ctrl+F4** - forces an immediate world rescan (normally happens every
  `RescanIntervalMs`).

These were used to confirm the core open/close logic works correctly
(verified live: Ctrl+F3 opened all 34 doors in a test world, Ctrl+F2
closed them all again).

## If it's still laggy

If `RescanIntervalMs` at 30 seconds is still too frequent for your setup,
try raising it further (e.g. 60000 or 120000). The trade-off is just how
quickly newly-built doors or newly-joined players get picked up - press
Ctrl+F4 any time to force an immediate refresh instead of waiting.

If `CheckIntervalMs` itself ever needs lowering further for responsiveness,
that should be cheap to do, since that pass never touches the full object
array - only the small cached list from the last rescan.

## What this mod does NOT touch

`HingeComponent` (the underlying mechanism) is also used by windows
(`BP_T2_Window_C`), confirmed in the object dump. This mod filters to only
the four known door classes - `BP_T1_Door_C`, `BP_T2_Door_C`, `BP_T3_Door_C`,
`BP_T3_CastleDoor_C` - so it will not touch windows or anything else. If new
door tiers get added later under a different class name, this list will
need a one-line update.

## Multiplayer / dedicated servers

`HingeComponent` replicates (`bReplicates = true`), so running this mod on
the host/server should be enough for the open/closed state to propagate to
connected clients - but this hasn't been tested in an actual multiplayer
session.
